diff options
author | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:40:17 -0500 |
---|---|---|
committer | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:40:17 -0500 |
commit | 33058f2b292b3a581333bdfb21b8f671898c5060 (patch) | |
tree | 51c3e392513ec574331b2d3f85c394445ea803c6 /files/zh-cn/learn/html | |
parent | 8b66d724f7caf0157093fb09cfec8fbd0c6ad50a (diff) | |
download | translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.gz translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.bz2 translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.zip |
initial commit
Diffstat (limited to 'files/zh-cn/learn/html')
42 files changed, 14953 insertions, 0 deletions
diff --git a/files/zh-cn/learn/html/forms/advanced_styling_for_html_forms/index.html b/files/zh-cn/learn/html/forms/advanced_styling_for_html_forms/index.html new file mode 100644 index 0000000000..94128b7229 --- /dev/null +++ b/files/zh-cn/learn/html/forms/advanced_styling_for_html_forms/index.html @@ -0,0 +1,467 @@ +--- +title: 高级设计 HTML 表单 +slug: Learn/HTML/Forms/Advanced_styling_for_HTML_forms +translation_of: Learn/Forms/Advanced_form_styling +--- +<div>{{LearnSidebar}}{{PreviousMenuNext("Learn/HTML/Forms/Styling_HTML_forms", "Learn/HTML/Forms/Property_compatibility_table_for_form_widgets", "Learn/HTML/Forms")}}</div> + +<p class="summary">在本文中,我们将看到<a href="https://developer.mozilla.org/en-US/docs/HTML">HTML</a>表单怎样使用<a href="https://developer.mozilla.org/en-US/docs/CSS">CSS</a>装饰难以定制的表单小部件。如<a href="/en-US/docs/HTML/Forms/Styling_HTML_forms">前面章节</a>所示,文本域和按钮完全可以使用CSS,现在我们将深入探索HTML表单样式。</p> + +<p>在继续之前,让我们回忆一下两种表单小部件:</p> + +<dl> + <dt>bad</dt> + <dd>这个元素很难设计,需要一些复杂的技巧,有时还涉及到高级的CSS3的知识。</dd> + <dt>ugly</dt> + <dd>忘记使用CSS来设计这些元素吧。你最多能做一点点事情,还不能保证可以跨浏览器,而且在它们出现时永远不能做到完全的受控。</dd> +</dl> + +<h2 id="CSS表现力">CSS表现力</h2> + +<p>除了文本框和按钮之外,使用其他表单小部件的主要问题是在许多情况下,CSS的表现不能满足设计复杂的小部件的要求。</p> + +<p>HTML和CSS最新的发展扩展了CSS的表现力:</p> + +<ul> + <li><a href="http://www.w3.org/TR/CSS21/selector.html#dynamic-pseudo-classes" rel="external" title="http://www.w3.org/TR/CSS21/selector.html#dynamic-pseudo-classes">CSS 2.1</a> 非常受限,只给出三个伪类: + + <ul> + <li>{{cssxref(":active")}}</li> + <li>{{cssxref(":focus")}}</li> + <li>{{cssxref(":hover")}}</li> + </ul> + </li> + <li><a href="http://www.w3.org/TR/css3-selectors/" rel="external" title="http://www.w3.org/TR/css3-selectors/">CSS Selector Level 3</a> 增加了三个与HTML表单相关的伪类: + <ul> + <li>{{cssxref(":enabled")}}</li> + <li>{{cssxref(":disabled")}}</li> + <li>{{cssxref(":checked")}}</li> + <li>{{cssxref(":indeterminate")}}</li> + </ul> + </li> + <li><a href="http://dev.w3.org/csswg/css3-ui/#pseudo-classes" rel="external" title="http://dev.w3.org/csswg/css3-ui/#pseudo-classes">CSS Basic UI Level 3</a> 也增加了几个伪类用于描述小部件的状态: + <ul> + <li>{{cssxref(":default")}}</li> + <li>{{cssxref(":valid")}}</li> + <li>{{cssxref(":invalid")}}</li> + <li>{{cssxref(":in-range")}}</li> + <li>{{cssxref(":out-of-range")}}</li> + <li>{{cssxref(":required")}}</li> + <li>{{cssxref(":optional")}}</li> + <li>{{cssxref(":read-only")}}</li> + <li>{{cssxref(":read-write")}}</li> + </ul> + </li> + <li><a href="http://dev.w3.org/csswg/selectors4/" rel="external" title="http://dev.w3.org/csswg/selectors4/">CSS Selector Level 4</a> 目前处于积极应用和重点讨论的状态,但并不打算为表单做更多的改善: + <ul> + <li>{{cssxref(":user-error")}} 只是改进了伪类{{cssxref(":invalid")}}。</li> + </ul> + </li> +</ul> + +<p>所有这一切是一个好的开端,但是有两个问题。首先,一些浏览器不需要实现CSS 2.1之上的特性。其次在设计像日期选择器这样的复杂的小部件时,这些实在不够好。</p> + +<p>浏览器厂家在CSS表现力在表单方面的扩展做了一些尝试,在某些情况下,知道什么可用也挺不错的。</p> + +<div class="warning"> +<p><strong>警告:</strong> 尽管 这些尝试很有趣,但<strong>它们是非标准的,也就是不可靠的。</strong>. 如果你使用它们(也许你并不常用),你要自己承担风险,使用非标准的属性<a href="http://www.alistapart.com/articles/every-time-you-call-a-proprietary-feature-css3-a-kitten-dies/" title="http://www.alistapart.com/articles/every-time-you-call-a-proprietary-feature-css3-a-kitten-dies/">对于Web并不是好事</a> 。</p> +</div> + +<ul> + <li><a href="/en-US/docs/CSS/CSS_Reference/Mozilla_Extensions" title="/en-US/docs/CSS/CSS_Reference/Mozilla_Extensions">Mozilla CSS 扩展</a> + + <ul> + <li>{{cssxref(":-moz-placeholder")}}</li> + <li>{{cssxref(":-moz-submit-invalid")}}</li> + <li>{{cssxref(":-moz-ui-invalid")}}</li> + <li>{{cssxref(":-moz-ui-valid")}}</li> + </ul> + </li> + <li><a href="/en-US/docs/CSS/CSS_Reference/Webkit_Extensions" title="/en-US/docs/CSS/CSS_Reference/Webkit_Extensions">WebKit CSS 扩展</a> + <ul> + <li>{{cssxref("::-webkit-input-placeholder")}}</li> + <li><a href="http://trac.webkit.org/wiki/Styling%20Form%20Controls" rel="external" title="http://trac.webkit.org/wiki/Styling Form Controls">其他</a></li> + </ul> + </li> + <li><a href="http://msdn.microsoft.com/en-us/library/ie/hh869403%28v=vs.85%29.aspx" rel="external" title="http://msdn.microsoft.com/en-us/library/ie/hh869403%28v=vs.85%29.aspx">Microsoft CSS 扩展</a> + <ul> + <li><code><a href="http://msdn.microsoft.com/en-us/library/ie/hh772745%28v=vs.85%29.aspx" rel="external" title="http://msdn.microsoft.com/en-us/library/ie/hh772745%28v=vs.85%29.aspx">:-ms-input-placeholder</a></code></li> + </ul> + </li> +</ul> + +<h3 id="控制表单元素的外观">控制表单元素的外观</h3> + +<p>基于WebKit(Chrome, Safari)和 Gecko(Firefox)的浏览器提供更高级的HTML部件定制。它们也实现了跨平台,因此需要一种方式把原生小部件转换为用户可设置样式的小部件。</p> + +<p>为此,它们使用了专有属性:{{cssxref("-webkit-appearance")}}或{{cssxref("-moz-appearance")}}。这<strong>些属性是非标准的,不应该使用。</strong>事实上,它们在WebKit 和Gecko中的表现也是不相同的。然而,有一个值很好用:<code>none</code>,用这个值,你(几乎完全)能控制一个已知小部件的样式。</p> + +<p>因此,如果你在应用一个元素的样式时遇到麻烦,可以尝试使用那些专有属性。我们下面有一些例子,这个属性最成功的例子是WebKit浏览器中的搜索域的样式:</p> + +<pre class="brush: html"><form> + <input type="search"> +</form></pre> + +<pre class="brush: css"><style> +input[type=search] { + border: 1px dotted #999; + border-radius: 0; + + -webkit-appearance: none; +} +</style></pre> + +<p>{{EmbedLiveSample("Controlling_the_appearance_of_form_elements", 250, 40)}}</p> + +<div class="note"> +<p><strong>注意:</strong>当我们谈及Web技术的时总是很难预测未来。扩展CSS表现力是很困难的,其他规范也做了一些探索性的工作,如<a href="http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html" rel="external" title="http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html">Shadow DOM</a>提供了一些观点。可完全设置样式的表单的问题还远未结束。</p> +</div> + +<h2 id="举例">举例</h2> + +<h3 id="复选框和单选按钮">复选框和单选按钮</h3> + +<p>独自设计复选框或单选按钮的样式是让人抓狂的。例如由于浏览器反应各不相同,在修改复选框和单选按钮的大小时,并不保证确实能改变它们。</p> + +<h4 id="一个简单的测试用例">一个简单的测试用例</h4> + +<p>让我们研究一下下面的测试用例:</p> + +<pre class="brush: html"><span><input type="checkbox"></span></pre> + +<pre class="brush: css">span { + display: inline-block; + background: red; +} + +input[type=checkbox] { + width : 100px; + height: 100px; +}</pre> + +<p>这里是不同的浏览器的处理方式:</p> + +<table> + <thead> + <tr> + <th scope="col">浏览器</th> + <th scope="col">视图</th> + </tr> + </thead> + <tbody> + <tr> + <td>Firefox 57 (Mac OSX)</td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15671/firefox-mac-checkbox.png"></td> + </tr> + <tr> + <td>Firefox 57 (Windows 10)</td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15691/firefox-windows-checkbox.png"></td> + </tr> + <tr> + <td>Chrome 63 (Mac OSX)</td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15676/chrome-mac-checkbox.png"></td> + </tr> + <tr> + <td>Chrome 63 (Windows 10)</td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15681/chrome-windows-checkbox.png"></td> + </tr> + <tr> + <td>Opera 49 (Mac OSX)</td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15701/opera-mac-checkbox.png"></td> + </tr> + <tr> + <td>Internet Explorer 11 (Windows 10)</td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15696/ie11-checkbox.png"></td> + </tr> + <tr> + <td>Edge 16 (Windows 10)</td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15686/edge-checkbox.png"></td> + </tr> + </tbody> +</table> + +<h4 id="更复杂的例子">更复杂的例子</h4> + +<p>由于Opera和Internet Explorer没有像{{cssxref("-webkit-appearance")}}或{{cssxref("-moz-appearance")}}这样的特性,使用它们是不合适的。幸运的是,CSS有足够多的表现方式可以找到解决方法。让我们做一个很普通的例子:</p> + +<pre class="brush: html"><form> + <fieldset> + <p> + <input type="checkbox" id="first" name="fruit-1" value="cherry"> + <label for="first">I like cherry</label> + </p> + <p> + <input type="checkbox" id="second" name="fruit-2" value="banana" disabled> + <label for="second">I can't like banana</label> + </p> + <p> + <input type="checkbox" id="third" name="fruit-3" value="strawberry"> + <label for="third">I like strawberry</label> + </p> + </fieldset> +</form></pre> + +<p>带有一些基本的样式:</p> + +<pre class="brush: css">body { + font: 1em sans-serif; +} + +form { + display: inline-block; + + padding: 0; + margin : 0; +} + +fieldset { + border : 1px solid #CCC; + border-radius: 5px; + margin : 0; + padding: 1em; +} + +label { + cursor : pointer; +} + +p { + margin : 0; +} + +p+p { + margin : .5em 0 0; +}</pre> + +<div class="note"> +<p><strong>注:下面的内容(仅限样式化 checkbox 部分)与英文版出入极大,猜测已经是过时内容</strong></p> +</div> + +<p>现在,让我们设计一个定制复选框的样式</p> + +<p>计划用自己的图像替换原生的复选框,首先需要准备复选框在所有状态下的图像,那些状态是:未选、已选、禁用不选、禁用已选。该图像将用作CSS精灵:</p> + +<p><img alt="Check box CSS Sprite" src="/files/4173/checkbox-sprite.png" style="height: 64px; width: 16px;"></p> + +<p>一开始要隐藏初始复选框。可以简单的把它们从页面视图中拿开。这里要考虑两个重要的事情:</p> + +<ul> + <li>不能用<code>display:none</code>来隐藏复选框,因为后面我们需要把复选框对用户可见。而使用<code>display:none</code>,用户不能再访问这个复选框,这就表示复选框不能选择或不选择。</li> + <li>我们将使用CSS3选择器来实现定制的样式,为了支持旧版浏览器,可以在所有选择器前设置{{cssxref(":root")}}伪类。目前所有我们需要支持的浏览器都支持{{cssxref(":root")}}伪类,但是其他的并不能保证。这是一个过滤旧的Internet Explorer的便利方式的例子。那些旧版浏览器将看到传统的复选框,而新式的浏览器可以看到定制的复选框。</li> +</ul> + +<pre class="brush: css">:root input[type=checkbox] { + /* original check box are push outside the viexport */ + position: absolute; + left: -1000em; +}</pre> + +<p>现在加上自己的图像就可以摆脱原来的复选框了,为此,要在初始的复选框后面加上{{HTMLElement("label")}}元素,并使用它的{{cssxref(":before")}}伪元素。因此在下面章节中,要使用<a href="/en-US/docs/CSS/Attribute_selectors" title="/en-US/docs/CSS/Attribute_selectors">selector属性</a>来选择复选框,然后使用<a href="/en-US/docs/CSS/Adjacent_sibling_selectors" title="/en-US/docs/CSS/Adjacent_sibling_selectors">adjacent sibling selector</a>来选择原有复选框后面的<code>label</code>。最后,访问{{cssxref(":before")}}伪元素来设计复选框显示定制样式。</p> + +<pre class="brush: css">:root input[type=checkbox] + label:before { + content: ""; + display: inline-block; + width : 16px; + height : 16px; + margin : 0 .5em 0 0; + background: url("https://developer.mozilla.org/files/4173/checkbox-sprite.png") no-repeat 0 0; + +/* The following is used to adjust the position of + the check boxes on the text baseline */ + + vertical-align: bottom; + position: relative; + bottom: 2px; +}</pre> + +<p>在初始复选框上使用{{cssxref(":checked")}}和{{cssxref(":disabled")}}伪类来改变定制复选框的状态。因为使用了CSS精灵,我们需要做的只是修改背景的位置。</p> + +<pre class="brush: css">:root input[type=checkbox]:checked + label:before { + background-position: 0 -16px; +} + +:root input[type=checkbox]:disabled + label:before { + background-position: 0 -32px; +} + +:root input[type=checkbox]:checked:disabled + label:before { + background-position: 0 -48px; +}</pre> + +<p>最后一件(但是很重要的)事情:当用户使用键盘从一个表单小部件导航到另一个表单小部件时,每个小部件都应该被显式聚焦。因为我们隐藏了初始的复选框,我们必须自己实现这个特性,让用户知道定制复选框在表单中的位置,下列的CSS实现了它们聚焦。</p> + +<pre class="brush: css">:root input[type=checkbox]:focus + label:before { + outline: 1px dotted black; +}</pre> + +<p>你可以在线查看结果:</p> + +<p>{{EmbedLiveSample("A_more_complex_example", 250, 130)}}</p> + +<h3 id="Dealing_with_the_select_nightmare">Dealing with the select nightmare</h3> + +<p>{{HTMLElement("select")}} 元素被认为是一个 "丑陋的" 组件,因为不可能保证它在跨平台时样式化的一致性。然而,有些事情是可能的。废话少说,让我们来看一个例子:</p> + +<pre class="brush: html"><select> + <option>Cherry</option> + <option>Banana</option> + <option>Strawberry</option> +</select></pre> + +<pre class="brush: css">select { + width : 80px; + padding : 10px; +} + +option { + padding : 5px; + color : red; +}</pre> + +<p>下面的表格显示了在两种情况下不同浏览器的处理方式。头两列就是上面的例子。后面两列使用了其他的定制CSS,可以对小部件的外观进行更多的控制:</p> + +<pre class="brush: css">select, option { + -webkit-appearance : none; /* To gain control over the appearance on WebKit/Chromium */ + -moz-appearance : none; /* To gain control over the appearance on Gecko */ + + /* To gain control over the appearance on and Trident (IE) + Note that it also works on Gecko and has partial effects on WebKit */ + background : none; +}</pre> + +<table> + <thead> + <tr> + <th colspan="1" rowspan="2" scope="col">Browser</th> + <th colspan="2" scope="col">Regular rendering</th> + <th colspan="2" scope="col">Tweaked rendering</th> + </tr> + <tr> + <th scope="col">closed</th> + <th scope="col">open</th> + <th scope="col">closed</th> + <th scope="col">open</th> + </tr> + </thead> + <tbody> + <tr> + <td>Firefox 57 (Mac OSX)</td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15672/firefox-mac-select-1-closed.png"></td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15673/firefox-mac-select-1-open.png"></td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15674/firefox-mac-select-2-closed.png"></td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15675/firefox-mac-select-2-open.png"></td> + </tr> + <tr> + <td>Firefox 57 (Windows 10)</td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15692/firefox-windows-select-1-closed.png"></td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15693/firefox-windows-select-1-open.png"></td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15694/firefox-windows-select-2-closed.png"></td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15695/firefox-windows-select-2-open.png"></td> + </tr> + <tr> + <td>Chrome 63 (Mac OSX)</td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15677/chrome-mac-select-1-closed.png"></td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15678/chrome-mac-select-1-open.png"></td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15684/chrome-windows-select-2-closed.png"></td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15680/chrome-mac-select-2-open.png"></td> + </tr> + <tr> + <td>Chrome 63 (Windows 10)</td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15682/chrome-windows-select-1-closed.png"></td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15683/chrome-windows-select-1-open.png"></td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15684/chrome-windows-select-2-closed.png"></td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15685/chrome-windows-select-2-open.png"></td> + </tr> + <tr> + <td>Opera 49 (Mac OSX)</td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15702/opera-mac-select-1-closed.png"></td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15703/opera-mac-select-1-open.png"></td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15704/opera-mac-select-2-closed.png"></td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15705/opera-mac-select-2-open.png"></td> + </tr> + <tr> + <td>IE11 (Windows 10)</td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15697/ie11-select-1-closed.png"></td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15698/ie11-select-1-open.png"></td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15699/ie11-select-2-closed.png"></td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15700/ie11-select-2-open.png"></td> + </tr> + <tr> + <td>Edge 16 (Windows 10)</td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15687/edge-select-1-closed.png"></td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15688/edge-select-1-open.png"></td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15689/edge-select-2-closed.png"></td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15690/edge-select-2-open.png"></td> + </tr> + </tbody> +</table> + +<p>如你所见,计时使用了<code>-*-appearance</code>属性的帮助,任然有一些遗留的问题:</p> + +<ul> + <li>不同的操作系统和浏览器对属性{{cssxref("padding")}} 属性的处理各不相同。</li> + <li>Internet Explorer旧版本不允许平滑样式</li> + <li>Firefox没有实现下拉箭头的样式。</li> + <li>如果要在下拉列表内实现{{HTMLElement("option")}}元素样式,Chrome和Opera浏览器的表现在不同的系统中是不一样的。</li> +</ul> + +<p>在我们的例子中,只使用了三个CSS属性,在考虑使用更多CSS属性时,可以想象是很混乱的。正如我们看到的,CSS始终不适合用来修改这些小部件的外观,但是仍然可以用来稍微做一些事情。如果愿意的话,可以演示一下在不同操作系统和浏览器之间的区别。</p> + +<p>我们也可以帮助了解在下一章节中哪个属性更合适:<a href="/en-US/docs/Properties_compatibility_table_for_forms_widgets" title="/en-US/docs/Properties_compatibility_table_for_forms_widgets">Properties compatibility table for form widgets</a></p> + +<h2 id="走向更完美表单之路:有用的库和polyfills(腻子)">走向更完美表单之路:有用的库和polyfills(腻子)</h2> + +<p>虽然对于复选框和单选按钮而言,CSS的表示方式足够丰富,但是对更高级的小部件来说差距仍然很大。即使可以用{{HTMLElement("select")}}元素作一些事情,但是对file小部件的样式完全没用。对于日期选择器也同样如此。</p> + +<p>要实现对表单小部件的完全控制,你别无选择,只能选择依靠JavaScript。在文章<a href="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets" title="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets">How to build custom form widgets</a>中,我们将看到具体的做法,其中还有一些非常有用的库:</p> + +<ul> + <li><a href="http://sprawsm.com/uni-form/" rel="external" title="http://sprawsm.com/uni-form/">Uni-form</a>是一个对采用CSS样式的表单标记实现标准化的框架,在使用jQuery时,还提供一些附加特性,但这是可选的。</li> + <li><a href="http://formalize.me/" rel="external" title="http://formalize.me/">Formalize</a>是对公共JavaScript框架的扩展(如jQuery, Dojo, YUI等),有助于规范和定制表单。</li> + <li><a href="http://www.emblematiq.com/lab/niceforms/" rel="external" title="http://www.emblematiq.com/lab/niceforms/">Niceforms</a>是一个独立的JavaScript方法,能提供web表单的完整定制。</li> +</ul> + +<p>下面的库不止应用于表单,他们在处理HTML表单时是非常有趣的:</p> + +<ul> + <li><a href="http://jqueryui.com/" rel="external" title="http://jqueryui.com/">jQuery UI</a>做了一些有趣的改进,可以定制象日期选择器(特别关注可访问性)这样的小部件。</li> + <li><a href="http://twitter.github.com/bootstrap/base-css.html#forms" rel="external" title="http://twitter.github.com/bootstrap/base-css.html#forms">Twitter Bootstrap</a>在规范表单时是非常有用的。</li> + <li><a href="http://afarkas.github.com/webshim/demos/demos/webforms.html" rel="external" title="http://afarkas.github.com/webshim/demos/demos/webforms.html">WebShim</a>是一个大型工具,可以用来处理浏览器对HTML5的支持。对web表单部分确实有用。</li> +</ul> + +<p>记住,使用CSS和JavaScript是有副作用的。所以在选择使用那些库时,应该在脚本失败的情况下能回滚样式表。脚本失败的原因很多,尤其在手机应用中,因此你需要尽可能好的设计你的Web站点或应用。</p> + +<h2 id="相关链接">相关链接</h2> + +<p>虽然HTML表单使用CSS仍有一些黑洞,但通常也有方法绕过它们。即使没有清楚的,通用的解决方案,但新式的浏览器也提供了新的可能性。目前最好的方法是更多的学习不同浏览器支持CSS的方式,并应用于HTML表单小部件。</p> + +<p>在本指南的下一章节中,我们将探讨不同的HTML表单小部件怎样很好的支持更重要的CSS属性:<a href="/en-US/docs/Properties_compatibility_table_for_forms_widgets" title="/en-US/docs/Properties_compatibility_table_for_forms_widgets">Properties compatibility table for form widgets</a>.</p> + +<h2 id="相关链接_2">相关链接</h2> + +<ul> + <li><a href="http://diveintohtml5.info/forms.html" rel="external" title="http://diveintohtml5.info/forms.html">Dive into HTML5: Forms</a></li> + <li><a href="http://www.smashingmagazine.com/2011/06/27/useful-ideas-and-guidelines-for-good-web-form-design/" rel="external" title="http://www.smashingmagazine.com/2011/06/27/useful-ideas-and-guidelines-for-good-web-form-design/">Useful ideas and guidelines for good web form design</a></li> +</ul> + +<p>{{PreviousMenuNext("Learn/HTML/Forms/Styling_HTML_forms", "Learn/HTML/Forms/Property_compatibility_table_for_form_widgets", "Learn/HTML/Forms")}}</p> + +<h2 id="在本单元中">在本单元中</h2> + +<ul> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Your_first_HTML_form">Your first HTML form</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/How_to_structure_an_HTML_form">How to structure an HTML form</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/The_native_form_widgets">The native form widgets</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Sending_and_retrieving_form_data">Sending form data</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Form_validation">Form data validation</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/How_to_build_custom_form_widgets">How to build custom form widgets</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Sending_forms_through_JavaScript">Sending forms through JavaScript</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/HTML_forms_in_legacy_browsers">HTML forms in legacy browsers</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Styling_HTML_forms">Styling HTML forms</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Advanced_styling_for_HTML_forms">Advanced styling for HTML forms</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Property_compatibility_table_for_form_widgets">Property compatibility table for form widgets</a></li> +</ul> + +<p> + <audio style="display: none;"></audio> +</p> diff --git a/files/zh-cn/learn/html/forms/data_form_validation/index.html b/files/zh-cn/learn/html/forms/data_form_validation/index.html new file mode 100644 index 0000000000..62758a26e6 --- /dev/null +++ b/files/zh-cn/learn/html/forms/data_form_validation/index.html @@ -0,0 +1,874 @@ +--- +title: 表单数据校验 +slug: Learn/HTML/Forms/Data_form_validation +tags: + - HTML +translation_of: Learn/Forms/Form_validation +--- +<p>{{LearnSidebar}}{{PreviousMenuNext("Learn/HTML/Forms/Sending_and_retrieving_form_data", "Learn/HTML/Forms/How_to_build_custom_form_widgets", "Learn/HTML/Forms")}}</p> + +<p class="summary">表单校验帮助我们确保用户以正确格式填写表单数据,确保提交的数据能使我们的应用程序正常工作。本文将告诉您需要了解的有关表单校验的内容。</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">预备知识:</th> + <td>计算机基础能力,对 <a href="/en-US/docs/Learn/HTML">HTML</a>、<a href="/en-US/docs/Learn/CSS">CSS</a> 和 <a href="/en-US/docs/Learn/JavaScript">JavaScript</a> 有一定的理解。</td> + </tr> + <tr> + <th scope="row">目标:</th> + <td>理解表单校验是什么,为什么它很重要,以及如何实现它。</td> + </tr> + </tbody> +</table> + +<h2 id="什么是表单数据校验?">什么是表单数据校验?</h2> + +<p>访问任何一个带注册表单的网站,你都会发现,当你提交了没有输入符合预期格式的信息的表单时,注册页面都会给你一个反馈,这些信息可能看起来像下面这样的:</p> + +<ul> + <li>“该字段是必填的”(该字段不能留空)</li> + <li>“请输入你的电话号码,它的格式是:xxx-xxxx”(它要求你输入的数据格式为三个数字接一个横杠,然后再接着是四个数字)</li> + <li>“请输入一个合法的邮箱地址”(如果你输入的数据不符合“somebody@example.com“的邮箱格式)</li> + <li>“你的密码长度应该是8至30位的,并且至少应该包含一个大写字母、一个符号以及一个数字”</li> +</ul> + +<p>这就是<strong>表单校验</strong> —— 当你向 Web 应用输入数据时,应用会验证你输入的数据是否是正确的。如果验证通过,应用允许提交这些数据到服务器并储存到数据库中(通常情况下),如果验证未通过,则 Web 应用会提示你有错误的数据,并且一般都会明确的告诉你错误发生在哪里。表单校验可以通过许多不同的方式实现。</p> + +<div class="note"> +<p><strong>译者注</strong>:下面一段在英文原文中已经删除</p> +</div> + +<p>(事实上,没有人愿意填写表单 —— 很多证据表明,用户对填写表单这件事情都感到很烦恼,如果他们在填写表单的过程中遇到一些自己无法理解的问题,通常都会导致他们直接离开你的 Web 应用,简而言之,<a href="https://www.slideshare.net/jwegesin/forms-suck/">表单是一个很烦人的东西</a>。)</p> + +<p>我们希望把填写表单变的越简单越好。那么,为什么我们还坚持进行表单的数据校验呢?这有三个最主要的原因:</p> + +<ul> + <li><strong>我们希望以正确的格式获取到正确的数据</strong> —— 如果我们的用户数据以不正确的格式存储,或者他们没有输入正确的信息/完全省略信息,我们的应用程序将无法正常运行。</li> + <li><strong>我们希望保护我们的用户</strong> ——强制用户输入安全的密码,有利于保护他们的账户信息。</li> + <li><strong>我们希望保护我们自己</strong> —— 恶意用户有很多通过滥用应用中缺乏保护的表单破坏应用的方法(具体请参见<a href="/zh-CN/docs/learn/Server-side/First_steps/Website_security">网站安全</a>)。</li> +</ul> + +<div class="blockIndicator warning"> +<p>警告: 永远不要相信从客户端传递到服务器的数据。 即使您的表单正确验证并防止输入格式错误,恶意用户仍然可以更改网络请求。</p> +</div> + +<h3 id="不同类型的表单数据校验">不同类型的表单数据校验</h3> + +<p>在 Web 中,你可能会遇见各种不同的表单校验:</p> + +<ul> + <li><strong>客户端校验</strong>发生在浏览器端,表单数据被提交到服务器之前,这种方式相较于服务器端校验来说,用户体验更好,它能实时的反馈用户的输入校验结果,这种类型的校验可以进一步细分成下面这些方式: + + <ul> + <li><strong>JavaScript</strong> 校验,这是可以完全自定义的实现方式;</li> + <li>HTML5 <strong>内置校验</strong>,这不需要 JavaScript ,而且性能更好,但是不能像JavaScript那样可自定义。</li> + </ul> + </li> + <li><strong>服务器端校验</strong>则是发生在浏览器提交数据并被服务器端程序接收之后 —— 通常服务器端校验都是发生在将数据写入数据库之前,如果数据没通过校验,则会直接从服务器端返回错误消息,并且告诉浏览器端发生错误的具体位置和原因,服务器端校验不像客户端校验那样有好的用户体验,因为它直到整个表单都提交后才能返回错误信息。但是服务器端校验是你的应用对抗错误/恶意数据的最后防线,在这之后,数据将被持久化至数据库。当今<a href="/zh-CN/docs/learn/Server-side/First_steps/Web_frameworks">所有的服务端框架</a>都提供了数据<strong>校验</strong>与<strong>清洁</strong>功能(让数据更安全)。</li> +</ul> + +<p>在真实的项目开发过程中,开发者一般都倾向于使用客户端校验与服务器端校验的组合校验方式以更好的保证数据的正确性与安全性。</p> + +<h2 id="使用内置表单数据校验">使用内置表单数据校验</h2> + +<p><a href="/en-US/docs/HTML/HTML5" title="/en-US/docs/HTML/HTML5">HTML5</a> 一个特别有用的新功能就是,可以在不写一行脚本代码的情况下,即对用户的输入进行数据校验,这都是通过表单元素的<a href="/zh-CN/docs/Web/Guide/HTML/HTML5/Constraint_validation">校验属性</a>实现的,这些属性可以让你定义一些规则,用于限定用户的输入,比如某个输入框是否必须输入,或者某个输入框的字符串的最小最大长度限制,或者某个输入框必须输入一个数字、邮箱地址等;还有数据必须匹配的模式。如果表单中输入的数据都符合这些限定规则,那么表示这个表单校验通过,否则则认为校验未通过。</p> + +<p>当一个元素校验通过时:</p> + +<ul> + <li>该元素将可以通过 CSS 伪类 {{cssxref(":valid")}} 进行特殊的样式化;</li> + <li>如果用户尝试提交表单,如果没有其它的控制来阻止该操作(比如JavaScript即可阻止提交),那么该表单的数据会被提交。</li> +</ul> + +<p>如果一个元素未校验通过:</p> + +<ul> + <li>该元素将可以通过 CSS 伪类 {{cssxref(":invalid")}} 进行特殊的样式化;</li> + <li>如果用户尝试提交表单,浏览器会展示出错误消息,并停止表单的提交。 </li> +</ul> + +<h3 id="input_元素的校验约束_—_starting_simple">input 元素的校验约束 — starting simple</h3> + +<p>在这一节,我们将会看到一些用于{{HTMLElement("input")}}元素校验的HTML5的特性。</p> + +<p>让我们用一个简单的例子开始 — 一个可以让你从香蕉或樱桃中选择你最喜欢的水果的input。 这个包含了一个简单的文本{{HTMLElement("input")}} 和一个与之匹配的label,还有一个 submit {{htmlelement("button")}}。你可以在GitHub <a href="https://github.com/mdn/learning-area/blob/master/html/forms/form-validation/fruit-start.html">fruit-start.html</a>找到源码,在线例子如下:</p> + +<div class="hidden"> +<h6 id="Hidden_code">Hidden code</h6> + +<pre class="brush: html"><form> + <label for="choose">Would you prefer a banana or cherry?</label> + <input id="choose" name="i_like"> + <button>Submit</button> +</form></pre> + +<pre class="brush: css">input:invalid { + border: 2px dashed red; +} + +input:valid { + border: 2px solid black; +}</pre> +</div> + +<p>{{EmbedLiveSample("Hidden_code", "100%", 50)}}</p> + +<p>开始之前,先拷贝一份 <code>fruit-start.html</code> 放在你硬盘上的新目录里。</p> + +<h3 id="required_属性">required 属性</h3> + +<p>最简单的HTML5校验功能是 {{htmlattrxref("required", "input")}}属性 — 如果要使输入成为必需的,则可以使用此属性标记元素。 当设置此属性时,如果输入为空,该表单将不会提交(并将显示错误消息),输入也将被视为无效。</p> + +<p>添加一个 <code>required</code> 属性到你的 input 元素, 如下所示:</p> + +<pre class="brush: html"><form> + <label for="choose">Would you prefer a banana or cherry?</label> + <input id="choose" name="i_like" required> + <button>Submit</button> +</form></pre> + +<p>同时注意在示例文件中包含的 CSS :</p> + +<pre class="brush: css">input:invalid { + border: 2px dashed red; +} + +input:valid { + border: 2px solid black; +}</pre> + +<p>以上样式效果为:在校验失败时 输入框会有一个亮红色的虚线边框, 在校验通过时会有一个更微妙的黑色边框。在以下示例中尝试新的行为:</p> + +<p>{{EmbedLiveSample("required_属性", "100%", 50)}}</p> + +<h3 id="使用正则表达式校验">使用正则表达式校验</h3> + +<p>另一个常用的校验功能是 {{htmlattrxref("pattern","input")}} 属性, 以 <a href="/zh-CN/docs/Web/JavaScript/Guide/Regular_Expressions" title="/en-US/docs/JavaScript/Guide/Regular_Expressions">Regular Expression</a> 作为 value 值. 正则表达式 (regex) 是一个可以用来匹配文本字符串中字符的组合的模式,所以它们是理想的表单校验器,也可以支持 JavaScript 中许多其它的用途。</p> + +<p>正则表达式相当复杂,我们不打算在本文中详尽地教你。</p> + +<p>下面是一些例子,让你对它们的工作原理有个基本的了解:</p> + +<ul> + <li><code>a</code> — 匹配一个字符<code>a</code>(不能匹配 <code>b</code>, <code>aa</code>等等.)</li> + <li><code>abc</code> — 匹配 <code>a</code>, 其次 <code>b</code>, 最后 <code>c</code>.</li> + <li><code>a*</code> — 匹配0个或者多个字符 <code>a</code> (<code>+</code> 代表至少匹配一个或者多个).</li> + <li><code>[^a]</code> — 匹配一个字符,但它<strong>不能</strong>是<code>a</code>.</li> + <li><code>a|b</code> — 匹配一个字符 <code>a</code> 或者 <code>b</code>.</li> + <li><code>[abc]</code> — 匹配一个字符,它可以是<code>a</code>,<code>b</code>或<code>c</code>.</li> + <li><code>[^abc]</code> — 匹配一个字符,但它<strong>不可以</strong>是<code>a</code>,<code>b</code>或<code>c</code>.</li> + <li><code>[a-z]</code> — 匹配字符范围 <code>a-z</code>且全部小写 (你可以使用 <code>[A-Za-z]</code> 涵盖大小写, 或 <code>[A-Z]</code> 来限制必须大写).</li> + <li><code>a.c</code> — 匹配字符 <code>a</code>,中间匹配任意一个字符,最后匹配字符<code> c</code>.</li> + <li><code>a{5}</code> — 匹配字符 <code>a</code>五次.</li> + <li><code>a{5,7}</code> — 匹配字符 <code>a</code>五到七次,不能多或者少.</li> +</ul> + +<p>你也可以在这些表达式中使用数字和其他字符, 例如:</p> + +<ul> + <li><code>[ -]</code> — 匹配一个空格或者虚线.</li> + <li><code>[0-9]</code> — 匹配数字范围0~9.</li> +</ul> + +<p>你可以任意地组合这些,你可以任意指定不同的部分:</p> + +<ul> + <li><code>[Ll].*k</code> — 匹配一个大写<code>L</code>或者小写的<code>l</code>, 之后匹配0个或多个任意类型的字符, 最后匹配一个小写字母 k.</li> + <li><code>[A-Z][A-Za-z' -]+</code> — 一个大写字母后面跟着匹配一个及以上的大小写字母或者中划线或者撇号或者空格. 这个可以用于校验英语会话中城市或城镇名, 但这需要首字母以大写开头,不包括其他字符,例如来自英国的Manchester, Ashton-under-lyne, 以及Bishop's Stortford等.</li> + <li><code>[0-9]{3}[ -][0-9]{3}[ -][0-9]{4}</code> — 简单的匹配一个美国内的电话号码 — 三个数字 0<code>-</code>9, 后面跟着一个空格或者中划线, 之后匹配三个数字 0<code>-</code>9, 再跟着一个空格或者中划线, 最后跟着四个数字 0<code>-</code>9. 但实际情况可能更加复杂,因为有些人会给号码加上括号什么的,这里的表达式只是用来做一个简单的演示.</li> +</ul> + +<p>不管怎么说, 让我们来实现这些例子 — 更新你的html文档表单增加一个 <code>pattern</code> 属性, 如下:</p> + +<pre class="brush: html"><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></pre> + +<div class="hidden"> +<pre class="brush: css">input:invalid { + border: 2px dashed red; +} + +input:valid { + border: 2px solid black; +}</pre> +</div> + +<p>{{EmbedLiveSample("使用正则表达式校验", "100%", 50)}}</p> + +<p>这个例子中, 该 {{HTMLElement("input")}} 元素接受两个值中的一个: 字符串 "banana" 或者字符串"cherry".</p> + +<p>在这个基础上, 尝试把<code>pattern</code> 属性内部的表达式改变成上面的几个例子, 然后看看这些表达式如何影响您可以输入的值以使输入值有效. 尝试写一些你自己设计的,看看它如何工作。尽量让他们与水果有关这样你的例子才会有意义.</p> + +<div class="note"> +<p><strong>注意:</strong> 一些 {{HTMLElement("input")}} 元素类型不需要{{htmlattrxref("pattern","input")}} 属性进行校验. 指定特定 <code>email</code> 类型 就会使用匹配电子邮件格式的正则表达式来校验(如果有 {{htmlattrxref("multiple","input")}} 属性请用逗号来分割多个邮箱). 进一步来说, 字段 <code>url</code> 类型则会自动校验输入的是否为一个合法的链接.</p> +</div> + +<div class="note"> +<p><strong>注意</strong>: 该 {{HTMLElement("textarea")}} 元素不支持{{htmlattrxref("pattern","input")}} 属性.</p> +</div> + +<h3 id="限制输入的长度">限制输入的长度</h3> + +<p>所有文本框 ({{HTMLElement("input")}} 或 {{HTMLElement("textarea")}}) 都可以使用{{htmlattrxref("minlength","input")}} 和 {{htmlattrxref("maxlength","input")}} 属性来限制长度. 如果输入的字段长度小于 {{htmlattrxref("minlength","input")}} 的值或大于 {{htmlattrxref("maxlength","input")}} 值则无效. 浏览器通常不会让用户在文本字段中键入比预期更长的值,不过更精细的设置总归是更好的。</p> + +<p>在数字条目中 (i.e. <code><input type="number"></code>), 该 {{htmlattrxref("min","input")}} 和 {{htmlattrxref("max","input")}} 属性同样提供校验约束.如果字段的值小于{{htmlattrxref("min","input")}} 属性的值或大于 {{htmlattrxref("max","input")}} 属性的值,该字段则无效.</p> + +<p>让我来看看另外一个例子. 创建一个 <a href="https://github.com/mdn/learning-area/blob/master/html/forms/form-validation/fruit-start.html">fruit-start.html</a> 文件副本.</p> + +<p>现在删除 <code><body></code> 元素中的内容, 替换成下面的代码:</p> + +<pre class="brush: html"><form> + <div> + <label for="choose">Would you prefer a banana or a cherry?</label> + <input id="choose" name="i_like" required minlength="6" maxlength="6"> + </div> + <div> + <label for="number">How many would you like?</label> + <input type="number" id="number" name="amount" value="1" min="1" max="10"> + </div> + <div> + <button>Submit</button> + </div> +</form></pre> + +<ul> + <li>这里我们看到 <code>text</code> 条目的属性<code>minlength</code> 和 <code>maxlength</code> 都为6 — 这 banana 和 cherry的长度都为6. 输入少于这个长度的字符显示无效, 大多浏览器不能输入超过该限制的长度的字符.</li> + <li>我们同时也能让 <code>number</code> 条目数值限制在 <code>min</code> 为 1 和 一个 <code>max</code> 为 10 中 — 输入超出范围则显示无效, 并且您将无法使用递增/递减箭头将该值改变到此范围之外。</li> +</ul> + +<div class="hidden"> +<pre>input:invalid { + border: 2px dashed red; +} + +input:valid { + border: 2px solid black; +} + +div { + margin-bottom: 10px; +}</pre> +</div> + +<p>这里是运行的例子:</p> + +<p>{{EmbedLiveSample("限制输入的长度", "100%", 70)}}</p> + +<div class="note"> +<p><strong>注意</strong>: <code><input type="number"></code> (或者其他类型, 像 <code>range</code>) 也可以获取到一个{{htmlattrxref("step", "input")}} 属性, 指定了值在增减过程固定改变的值 (如向上增加和向下减少的按钮).</p> +</div> + +<h3 id="完整的例子">完整的例子</h3> + +<p>这里就是一个完整的展示 HTML 中使用校验属性的例子:</p> + +<pre class="brush: html"><form> + <p> + <fieldset> + <legend>Title<abbr title="This field is mandatory">*</abbr></legend> + <input type="radio" required name="title" id="r1" value="Mr"><label for="r1">Mr.</label> + <input type="radio" required name="title" id="r2" value="Ms"><label for="r2">Ms.</label> + </fieldset> + </p> + <p> + <label for="n1">How old are you?</label> + <!-- 这里的pattern属性可以用作不支持number类input浏览器的备用方法 + 请注意当与数字输入框一起使用时,支持pattern属性的浏览器会使它沉默失效。 + 它仅仅是在这里用作备用 --> + <input type="number" min="12" max="120" step="1" id="n1" name="age" + pattern="\d+"> + </p> + <p> + <label for="t1">What's your favorite fruit?<abbr title="This field is mandatory">*</abbr></label> + <input type="text" id="t1" name="fruit" list="l1" required + pattern="[Bb]anana|[Cc]herry|[Aa]pple|[Ss]trawberry|[Ll]emon|[Oo]range"> + <datalist id="l1"> + <option>Banana</option> + <option>Cherry</option> + <option>Apple</option> + <option>Strawberry</option> + <option>Lemon</option> + <option>Orange</option> + </datalist> + </p> + <p> + <label for="t2">What's your e-mail?</label> + <input type="email" id="t2" name="email"> + </p> + <p> + <label for="t3">Leave a short message</label> + <textarea id="t3" name="msg" maxlength="140" rows="5"></textarea> + </p> + <p> + <button>Submit</button> + </p> +</form></pre> + +<pre class="brush: css">body { + font: 1em sans-serif; + padding: 0; + margin : 0; +} + +form { + max-width: 200px; + margin: 0; + padding: 0 5px; +} + +p > label { + display: block; +} + +input[type=text], +input[type=email], +input[type=number], +textarea, +fieldset { +/* 需要在基于WebKit的浏览器上对表单元素进行恰当的样式设置 */ + -webkit-appearance: none; + + width : 100%; + border: 1px solid #333; + margin: 0; + + font-family: inherit; + font-size: 90%; + + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +input:invalid { + box-shadow: 0 0 5px 1px red; +} + +input:focus:invalid { + outline: none; +}</pre> + +<p>{{EmbedLiveSample("完整的例子", "100%", 420)}}</p> + +<h3 id="自定义错误信息">自定义错误信息</h3> + +<p>正如我们上面所看到的例子, 每次我们提交无效的表单数据时, 浏览器总会显示错误信息. 但是显示的信息取决于你所使用的浏览器.</p> + +<p>这些自动生成的错误有两个缺点:</p> + +<ul> + <li>没有标准可以让 CSS 来改变他们的界面外观.</li> + <li>这依赖于他们使用的浏览器环境, 意味着你可能在这种语言的页面里得到另一种语言的错误提示.</li> +</ul> + +<table> + <caption>在英文页面上的法语反馈信息版本</caption> + <thead> + <tr> + <th scope="col">浏览器</th> + <th scope="col">渲染</th> + </tr> + </thead> + <tbody> + <tr> + <td>Firefox 17 (Windows 7)</td> + <td><img alt="Example of an error message with Firefox in French on an English page" src="/files/4329/error-firefox-win7.png" style="height: 97px; width: 228px;"></td> + </tr> + <tr> + <td>Chrome 22 (Windows 7)</td> + <td><img alt="Example of an error message with Chrome in French on an English page" src="/files/4327/error-chrome-win7.png" style="height: 96px; width: 261px;"></td> + </tr> + <tr> + <td>Opera 12.10 (Mac OSX)</td> + <td><img alt="Example of an error message with Opera in French on an English page" src="/files/4331/error-opera-macos.png" style="height: 83px; width: 218px;"></td> + </tr> + </tbody> +</table> + +<p>要自定义这些消息的外观和文本, 你必须使用 JavaScript; 不能使用 HTML 和 CSS 来改变.</p> + +<p>HTML5 提供 <a href="http://www.w3.org/TR/html5/forms.html#the-constraint-validation-api" rel="external" title="http://www.w3.org/TR/html5/forms.html#the-constraint-validation-api">constraint validation API</a> 来检测和自定义表单元素的状态. 除此之外,他可以改变错误信息的文本. 让我们快速的看一个例子:</p> + +<pre class="brush: html"><form> + <label for="mail">I would like you to provide me an e-mail</label> + <input type="email" id="mail" name="mail"> + <button>Submit</button> +</form></pre> + +<p>在JavaScript 中, 你调用 <a href="/en-US/docs/HTML/HTML5/Constraint_validation#Constraint_API's_element.setCustomValidity()" title="/en-US/docs/HTML/HTML5/Constraint_validation#Constraint_API's_element.setCustomValidity()"><code>setCustomValidity()</code></a> 方法:</p> + +<pre class="brush: js">var email = document.getElementById("mail"); + +email.addEventListener("input", function (event) { + if (email.validity.typeMismatch) { + email.setCustomValidity("I expect an e-mail, darling!"); + } else { + email.setCustomValidity(""); + } +});</pre> + +<p>{{EmbedLiveSample("自定义错误信息", "100%", 50)}}</p> + +<h2 id="使用_JavaScript校验表单"> 使用 JavaScript校验表单</h2> + +<p>如果你想控制原生错误信息的界面外观,或者你想处理不支持HTML内置表单校验的浏览器,则必须使用 Javascript。</p> + +<h3 id="约束校验的_API">约束校验的 API</h3> + +<p>越来越多的浏览器支持限制校验API,并且这逐渐变得可靠。这些 API 由成组的方法和属性构成,可在特定的表单元素接口上调用:</p> + +<ul> + <li><a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLButtonElement">HTMLButtonElement</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLFieldSetElement">HTMLFieldSetElement</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement">HTMLInputElement</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLOutputElement">HTMLOutputElement</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement">HTMLSelectElement</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLTextAreaElement">HTMLTextAreaElement</a></li> +</ul> + +<h4 id="约束校验的_API_及属性">约束校验的 API 及属性</h4> + +<table> + <thead> + <tr> + <th scope="col">属性</th> + <th scope="col">描述</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>validationMessage</code></td> + <td>一个本地化消息,描述元素不满足校验条件时(如果有的话)的文本信息。如果元素无需校验(<code>willValidate</code> 为 <code>false</code>),或元素的值满足校验条件时,为空字符串。</td> + </tr> + <tr> + <td><code>validity</code></td> + <td>一个 {{domxref("ValidityState")}} 对象,描述元素的验证状态。详见有关可能的验证状态的文章。</td> + </tr> + <tr> + <td><code>validity.customError</code></td> + <td>如果元素设置了自定义错误,返回 <code>true</code> ;否则返回<code>false</code>。</td> + </tr> + <tr> + <td><code>validity.patternMismatch</code></td> + <td>如果元素的值不匹配所设置的正则表达式,返回 <code>true</code>,否则返回 <code>false</code>。<br> + <br> + 当此属性为 <code>true</code> 时,元素将命中 {{cssxref(":invalid")}} CSS 伪类。</td> + </tr> + <tr> + <td><code>validity.rangeOverflow</code></td> + <td>如果元素的值高于所设置的最大值,返回 <code>true</code>,否则返回 <code>false</code>。<br> + <br> + 当此属性为 <code>true</code> 时,元素将命中 {{cssxref(":invalid")}} CSS 伪类。</td> + </tr> + <tr> + <td><code>validity.rangeUnderflow</code></td> + <td>如果元素的值低于所设置的最小值,返回 <code>true</code>,否则返回 <code>false</code>。<br> + <br> + 当此属性为 <code>true</code> 时,元素将命中 {{cssxref(":invalid")}} CSS 伪类。</td> + </tr> + <tr> + <td><code>validity.stepMismatch</code></td> + <td>如果元素的值不符合 step 属性的规则,返回 <code>true</code>,否则返回 <code>false</code>。<br> + <br> + 当此属性为 <code>true</code> 时,元素将命中 {{cssxref(":invalid")}} CSS 伪类。</td> + </tr> + <tr> + <td><code>validity.tooLong</code></td> + <td>如果元素的值超过所设置的最大长度,返回 <code>true</code>,否则返回 <code>false</code>。<br> + <br> + 当此属性为 <code>true</code> 时,元素将命中 {{cssxref(":invalid")}} CSS 伪类。</td> + </tr> + <tr> + <td><code>validity.typeMismatch</code></td> + <td>如果元素的值出现语法错误,返回 <code>true</code>,否则返回 <code>false</code>。<br> + <br> + 当此属性为 <code>true</code> 时,元素将命中 {{cssxref(":invalid")}} CSS 伪类。</td> + </tr> + <tr> + <td><code>validity.valid</code></td> + <td>如果元素的值不存在校验问题,返回 <code>true</code>,否则返回 <code>false</code>。<br> + <br> + 当此属性为 <code>true</code> 时,元素将命中 {{cssxref(":valid")}} CSS 伪类,否则命中 {{cssxref(":invalid")}} CSS 伪类。</td> + </tr> + <tr> + <td><code>validity.valueMissing</code></td> + <td>如果元素设置了 required 属性且值为空,返回 <code>true</code>,否则返回 <code>false</code>。<br> + <br> + 当此属性为 true 时,元素将命中 {{cssxref(":invalid")}} CSS 伪类。</td> + </tr> + <tr> + <td><code>willValidate</code></td> + <td>如果元素在表单提交时将被校验,返回 <code>true</code>,否则返回 <code>false</code>。</td> + </tr> + </tbody> +</table> + +<h4 id="约束校验_API_的方法">约束校验 API 的方法</h4> + +<table> + <thead> + <tr> + <th scope="col">方法</th> + <th scope="col">描述</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>checkValidity()</code></td> + <td>如果元素的值不存在校验问题,返回 <code>true</code>,否则返回 <code>false</code>。如果元素校验失败,此方法会触发{{event("invalid")}} 事件。</td> + </tr> + <tr> + <td>{{domxref("HTMLFormElement.reportValidity()")}}</td> + <td>如果元素或它的子元素控件符合校验的限制,返回 <code>true</code> . 当返回为 <code>false</code> 时, 对每个无效元素可撤销 {{event("invalid")}} 事件会被唤起并且校验错误会报告给用户 。</td> + </tr> + <tr> + <td> + <p><code>setCustomValidity(<em>message</em>)</code></p> + </td> + <td>为元素添加一个自定义的错误消息;如果设置了自定义错误消息,该元素被认为是无效的,则显示指定的错误。这允许你使用 JavaScript 代码来建立校验失败,而不是用标准约束校验 API 所提供的。这些自定义信息将在向用户报告错误时显示。<br> + <br> + 如果参数为空,则清空自定义错误。</td> + </tr> + </tbody> +</table> + +<p>对于旧版浏览器,可以使用 <a href="https://hyperform.js.org/" rel="external" title="https://hyperform.js.org/">polyfill(例如 Hyperform</a>),来弥补其对约束校验 API 支持的不足。既然你已经使用 JavaScript,在您的网站或 Web 应用程序的设计和实现中使用 polyfill 并不是累赘。</p> + +<h4 id="使用约束校验_API_的例子">使用约束校验 API 的例子</h4> + +<p>让我们看看如何使用这个 API 来构建自定义错误消息。首先,HTML:</p> + +<pre class="brush: html"><form novalidate> + <p> + <label for="mail"> + <span>Please enter an email address:</span> + <input type="email" id="mail" name="mail"> + <span class="error" aria-live="polite"></span> + </label> + </p> + <button>Submit</button> +</form></pre> + +<p>这个简单的表单使用 {{htmlattrxref("novalidate","form")}} 属性关闭浏览器的自动校验;这允许我们使用脚本控制表单校验。但是,这并不禁止对约束校验 API的支持或是以下 CSS 伪类:{{cssxref(":valid")}}、{{cssxref(":invalid")}}、{{cssxref(":in-range")}} 、{{cssxref(":out-of-range")}} 的应用。这意味着,即使浏览器在发送数据之前没有自动检查表单的有效性,您仍然可以自己做,并相应地设置表单的样式。</p> + +<p><a href="/en-US/docs/Accessibility/ARIA/ARIA_Live_Regions" title="/en-US/docs/Accessibility/ARIA/ARIA_Live_Regions"><code>aria-live</code></a> 属性确保我们的自定义错误信息将呈现给所有人,包括使用屏幕阅读器等辅助技术的人。</p> + +<h5 id="CSS">CSS</h5> + +<p>以下 CSS 样式使我们的表单和其错误输出看起来更有吸引力。</p> + +<pre class="brush: css">/* 仅为了使示例更好看 */ +body { + font: 1em sans-serif; + padding: 0; + margin : 0; +} + +form { + max-width: 200px; +} + +p * { + display: block; +} + +input[type=email]{ + -webkit-appearance: none; + + width: 100%; + border: 1px solid #333; + margin: 0; + + font-family: inherit; + font-size: 90%; + + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +/* 校验失败的元素样式 */ +input:invalid{ + border-color: #900; + background-color: #FDD; +} + +input:focus:invalid { + outline: none; +} + +/* 错误消息的样式 */ +.error { + width : 100%; + padding: 0; + + font-size: 80%; + color: white; + background-color: #900; + border-radius: 0 0 5px 5px; + + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +.error.active { + padding: 0.3em; +}</pre> + +<h5 id="JavaScript">JavaScript</h5> + +<p>以下 JavaScript 代码演示如何设置自定义错误校验。</p> + +<pre class="brush: js">// 有许多方式可以获取 DOM 节点;在此我们获取表单本身和 +// email 输入框,以及我们将放置错误信息的 span 元素。 + +var form = document.getElementsByTagName('form')[0]; +var email = document.getElementById('mail'); +var error = document.querySelector('.error'); + +email.addEventListener("input", function (event) { + // 当用户输入信息时,校验 email 字段 + if (email.validity.valid) { + // 如果校验通过,清除已显示的错误消息 + error.innerHTML = ""; // 重置消息的内容 + error.className = "error"; // 重置消息的显示状态 + } +}, false); +form.addEventListener("submit", function (event) { + // 当用户提交表单时,校验 email 字段 + if (!email.validity.valid) { + + // 如果校验失败,显示一个自定义错误 + error.innerHTML = "I expect an e-mail, darling!"; + error.className = "error active"; + // 还需要阻止表单提交事件,以取消数据传送 + event.preventDefault(); + } +}, false);</pre> + +<p>这是运行结果:</p> + +<p>{{EmbedLiveSample("使用校验约束_API_的例子", "100%", 130)}}</p> + +<p>约束校验 API 为您提供了一个强大的工具来处理表单校验,让您可以对用户界面进行远超过仅仅使用 HTML 和 CSS所能得到的控制。</p> + +<h3 id="不使用内建_API_时的表单校验">不使用内建 API 时的表单校验</h3> + +<p>有时,例如使用旧版浏览器或<a href="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets" title="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets">自定义小部件</a>,您将无法(或不希望)使用约束校验API。 在这种情况下,您仍然可以使用 JavaScript 来校验您的表单。 校验表单比起真实数据校验更像是一个用户界面问题。</p> + +<p>要校验表单,您必须问自己几个问题:</p> + +<dl> + <dt>我应该进行什么样的校验?</dt> + <dd>你需要确定如何校验你的数据:字符串操作,类型转换,正则表达式等。这取决于你。 只要记住,表单数据一般都是文本,并总是以字符串形式提供给脚本。</dd> + <dt>如果表单校验失败,我该怎么办?</dt> + <dd>这显然是一个 UI 问题。 您必须决定表单的行为方式:表单是否发送数据? 是否突出显示错误的字段?是否显示错误消息?</dd> + <dt>如何帮助用户纠正无效数据?</dt> + <dd>为了减少用户的挫折感,提供尽可能多的有用的信息是非常重要的,以便引导他们纠正他们的输入。 您应该提供前期建议,以便他们知道预期的输入是什么以及明确的错误消息。 如果您想深入了解表单校验用户界面要求,那么您应该阅读一些有用的文章: + <ul> + <li>SmashingMagazine: <a href="http://uxdesign.smashingmagazine.com/2012/06/27/form-field-validation-errors-only-approach/" rel="external" title="http://uxdesign.smashingmagazine.com/2012/06/27/form-field-validation-errors-only-approach/">Form-Field Validation: The Errors-Only Approach</a></li> + <li>SmashingMagazine: <a href="http://www.smashingmagazine.com/2009/07/07/web-form-validation-best-practices-and-tutorials/" rel="external" title="http://www.smashingmagazine.com/2009/07/07/web-form-validation-best-practices-and-tutorials/">Web Form Validation: Best Practices and Tutorials</a></li> + <li>Six Revision: <a href="http://sixrevisions.com/user-interface/best-practices-for-hints-and-validation-in-web-forms/" rel="external" title="http://sixrevisions.com/user-interface/best-practices-for-hints-and-validation-in-web-forms/">Best Practices for Hints and Validation in Web Forms</a></li> + <li>A List Apart: <a href="http://www.alistapart.com/articles/inline-validation-in-web-forms/" rel="external" title="http://www.alistapart.com/articles/inline-validation-in-web-forms/">Inline Validation in Web Forms</a></li> + </ul> + </dd> +</dl> + +<h4 id="不使用约束校验API_的例子">不使用约束校验API 的例子</h4> + +<p>为了说明这一点,让我们重构一下前面的例子,以便它可以在旧版浏览器中使用:</p> + +<pre class="brush: html"><form> + <p> + <label for="mail"> + <span>Please enter an email address:</span> + <input type="text" class="mail" id="mail" name="mail"> + <span class="error" aria-live="polite"></span> + </label> + <p> + <!-- Some legacy browsers need to have the `type` attribute + explicitly set to `submit` on the `button`element --> + <button type="submit">Submit</button> +</form></pre> + +<p>正如你所看到的,HTML 几乎是一样的;我们只是关闭了 HTML 校验功能。 请注意,<a href="/en-US/docs/Accessibility/ARIA" title="/en-US/docs/Accessibility/ARIA">ARIA</a> 是与 HTML5 无关的独立规范。</p> + +<h5 id="CSS_2">CSS</h5> + +<p>同样的,CSS也不需要太多的改动, 我们只需将 {{cssxref(":invalid")}} 伪类变成真实的类,并避免使用不适用于 Internet Explorer 6 的属性选择器。</p> + +<pre class="brush: css">/* 仅为了使示例更好看 */ +body { + font: 1em sans-serif; + padding: 0; + margin : 0; +} + +form { + max-width: 200px; +} + +p * { + display: block; +} + +input.mail { + -webkit-appearance: none; + + width: 100%; + border: 1px solid #333; + margin: 0; + + font-family: inherit; + font-size: 90%; + + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +/* 校验失败的元素样式 */ +input.invalid{ + border-color: #900; + background-color: #FDD; +} + +input:focus.invalid { + outline: none; +} + +/* 错误消息的样式 */ +.error { + width : 100%; + padding: 0; + + font-size: 80%; + color: white; + background-color: #900; + border-radius: 0 0 5px 5px; + + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +.error.active { + padding: 0.3em; +}</pre> + +<h5 id="JavaScript_2">JavaScript</h5> + +<p>JavaScript 代码有很大的变化,需要做更多的工作。</p> + +<pre class="brush: js">// 使用旧版浏览器选择 DOM 节点的方法较少 +var form = document.getElementsByTagName('form')[0]; +var email = document.getElementById('mail'); + +// 以下是在 DOM 中访问下一个兄弟元素的技巧 +// 这比较危险,很容易引起无限循环 +// 在现代浏览器中,应该使用 element.nextElementSibling +var error = email; +while ((error = error.nextSibling).nodeType != 1); + +// 按照 HTML5 规范 +var emailRegExp = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/; + +// 许多旧版浏览器不支持 addEventListener 方法 +// 这只是其中一种简单的处理方法 +function addEvent(element, event, callback) { + var previousEventCallBack = element["on"+event]; + element["on"+event] = function (e) { + var output = callback(e); + + // 返回 `false` 来停止回调链,并中断事件的执行 + if (output === false) return false; + + if (typeof previousEventCallBack === 'function') { + output = previousEventCallBack(e); + if(output === false) return false; + } + } +}; + +// 现在我们可以重构字段的约束校验了 +// 由于不使用 CSS 伪类, 我们必须明确地设置 valid 或 invalid 类到 email 字段上 +addEvent(window, "load", function () { + // 在这里验证字段是否为空(请记住,该字段不是必需的) + // 如果非空,检查它的内容格式是不是合格的 e-mail 地址 + var test = email.value.length === 0 || emailRegExp.test(email.value); + + email.className = test ? "valid" : "invalid"; +}); + +// 处理用户输入事件 +addEvent(email, "input", function () { + var test = email.value.length === 0 || emailRegExp.test(email.value); + if (test) { + email.className = "valid"; + error.innerHTML = ""; + error.className = "error"; + } else { + email.className = "invalid"; + } +}); + +// 处理表单提交事件 +addEvent(form, "submit", function () { + var test = email.value.length === 0 || emailRegExp.test(email.value); + + if (!test) { + email.className = "invalid"; + error.innerHTML = "I expect an e-mail, darling!"; + error.className = "error active"; + + // 某些旧版浏览器不支持 event.preventDefault() 方法 + return false; + } else { + email.className = "valid"; + error.innerHTML = ""; + error.className = "error"; + } +});</pre> + +<p>该结果如下:</p> + +<p>{{EmbedLiveSample("不使用内建_API_时的表单校验", "100%", 130)}}</p> + +<p>正如你所看到的,建立自己的校验系统并不难。 困难的部分是使其足够通用,以跨平台和任何形式使用它可以创建。 有许多库可用于执行表单校验; 你应该毫不犹豫地使用它们。 这里有一些例子:</p> + +<ul> + <li>独立的库(原生 Javascript 实现): + <ul> + <li><a href="http://rickharrison.github.com/validate.js/" rel="external" title="http://rickharrison.github.com/validate.js/">Validate.js</a></li> + </ul> + </li> + <li>jQuery 插件: + <ul> + <li><a href="http://bassistance.de/jquery-plugins/jquery-plugin-validation/" rel="external" title="http://bassistance.de/jquery-plugins/jquery-plugin-validation/">Validation</a></li> + <li><a href="http://unwrongest.com/projects/valid8/" rel="external" title="http://unwrongest.com/projects/valid8/">Valid8</a><span style="display: none;"> </span></li> + </ul> + </li> +</ul> + +<h4 id="远程校验"> 远程校验</h4> + +<p>在某些情况下,执行一些远程校验可能很有用。 当用户输入的数据与存储在应用程序服务器端的附加数据绑定时,这种校验是必要的。 一个应用实例就是注册表单,在这里你需要一个用户名。 为了避免重复,执行一个 AJAX 请求来检查用户名的可用性,要比让先用户发送数据,然后因为表单重复了返回错误信息要好得多。</p> + +<p>执行这样的校验需要采取一些预防措施:</p> + +<ul> + <li>它要求公开 API 和一些数据;您需要确保它不是敏感数据。</li> + <li>网络滞后需要执行异步校验。这需要一些用户界面的工作,以确保如果校验没有适当的执行,用户不会被阻止。</li> +</ul> + +<h2 id="结论">结论</h2> + +<p>表单校验并不需要复杂的 JavaScript,但它需要对用户的仔细考虑。 一定要记住帮助您的用户更正他提供的数据。 为此,请务必:</p> + +<ul> + <li>显示明确的错误消息。</li> + <li>放宽输入格式限制。</li> + <li>指出错误发生的位置(特别是在大型表单中)。</li> +</ul> + +<p>{{PreviousMenuNext("Learn/HTML/Forms/Sending_and_retrieving_form_data", "Learn/HTML/Forms/How_to_build_custom_form_widgets", "Learn/HTML/Forms")}}</p> diff --git a/files/zh-cn/learn/html/forms/how_to_build_custom_form_widgets/example_1/index.html b/files/zh-cn/learn/html/forms/how_to_build_custom_form_widgets/example_1/index.html new file mode 100644 index 0000000000..93cf5069c2 --- /dev/null +++ b/files/zh-cn/learn/html/forms/how_to_build_custom_form_widgets/example_1/index.html @@ -0,0 +1,418 @@ +--- +title: Example 1 +slug: Learn/HTML/Forms/How_to_build_custom_form_widgets/Example_1 +tags: + - HTML + - 表单 +translation_of: Learn/Forms/How_to_build_custom_form_controls/Example_1 +--- +<p>这是第一个<a href="/en-US/docs/Web/Guide/HTML/Forms/How_to_build_custom_form_widgets">如果构建自定义表单小部件</a>的代码解释事例。</p> + +<h2 id="Basic_state" name="Basic_state">基本状态</h2> + +<h3 id="Basic_state_HTML" name="Basic_state_HTML">HTML</h3> + +<pre class="brush: html"><div class="select"> + <span class="value">Cherry</span> + <ul class="optList hidden"> + <li class="option">Cherry</li> + <li class="option">Lemon</li> + <li class="option">Banana</li> + <li class="option">Strawberry</li> + <li class="option">Apple</li> + </ul> +</div></pre> + +<h3 id="Basic_state_CSS" name="Basic_state_CSS">CSS</h3> + +<pre class="brush: css">/* --------------- */ +/* Required Styles */ +/* --------------- */ + +.select { + position: relative; + display : inline-block; +} + +.select.active, +.select:focus { + box-shadow: 0 0 3px 1px #227755; + outline: none; +} + +.select .optList { + position: absolute; + top : 100%; + left : 0; +} + +.select .optList.hidden { + max-height: 0; + visibility: hidden; +} + +/* ------------ */ +/* Fancy Styles */ +/* ------------ */ + +.select { + font-size : 0.625em; /* 10px */ + font-family : Verdana, Arial, sans-serif; + + -moz-box-sizing : border-box; + box-sizing : border-box; + + padding : 0.1em 2.5em 0.2em 0.5em; /* 1px 25px 2px 5px */ + width : 10em; /* 100px */ + + border : 0.2em solid #000; /* 2px */ + border-radius : 0.4em; /* 4px */ + + box-shadow : 0 0.1em 0.2em rgba(0,0,0,.45); /* 0 1px 2px */ + + background : #F0F0F0; + background : -webkit-linear-gradient(90deg, #E3E3E3, #fcfcfc 50%, #f0f0f0); + background : linear-gradient(0deg, #E3E3E3, #fcfcfc 50%, #f0f0f0); +} + +.select .value { + display : inline-block; + width : 100%; + overflow : hidden; + + white-space : nowrap; + text-overflow : ellipsis; + vertical-align: top; +} + +.select:after { + content : "▼"; + position: absolute; + z-index : 1; + height : 100%; + width : 2em; /* 20px */ + top : 0; + right : 0; + + padding-top : .1em; + + -moz-box-sizing : border-box; + box-sizing : border-box; + + text-align : center; + + border-left : .2em solid #000; + border-radius: 0 .1em .1em 0; + + background-color : #000; + color : #FFF; +} + +.select .optList { + z-index : 2; + + list-style: none; + margin : 0; + padding: 0; + + background: #f0f0f0; + border: .2em solid #000; + border-top-width : .1em; + border-radius: 0 0 .4em .4em; + + box-shadow: 0 .2em .4em rgba(0,0,0,.4); + + -moz-box-sizing : border-box; + box-sizing : border-box; + + min-width : 100%; + max-height: 10em; /* 100px */ + overflow-y: auto; + overflow-x: hidden; +} + +.select .option { + padding: .2em .3em; +} + +.select .highlight { + background: #000; + color: #FFFFFF; +} +</pre> + +<h3 id="基本状态结果">基本状态结果</h3> + +<div>{{ EmbedLiveSample('Basic_state', 120, 130) }}</div> + +<h2 id="Active_state" name="Active_state">活动状态</h2> + +<h3 id="Active_state_HTML" name="Active_state_HTML">HTML</h3> + +<pre class="brush:html"><div class="select active"> + <span class="value">Cherry</span> + <ul class="optList hidden"> + <li class="option">Cherry</li> + <li class="option">Lemon</li> + <li class="option">Banana</li> + <li class="option">Strawberry</li> + <li class="option">Apple</li> + </ul> +</div></pre> + +<h3 id="Active_state_CSS" name="Active_state_CSS">CSS</h3> + +<pre class="brush:css">/* --------------- */ +/* Required Styles */ +/* --------------- */ + +.select { + position: relative; + display : inline-block; +} + +.select.active, +.select:focus { + box-shadow: 0 0 3px 1px #227755; + outline: none; +} + +.select .optList { + position: absolute; + top : 100%; + left : 0; +} + +.select .optList.hidden { + max-height: 0; + visibility: hidden; +} + +/* ------------ */ +/* Fancy Styles */ +/* ------------ */ + +.select { + font-size : 0.625em; /* 10px */ + font-family : Verdana, Arial, sans-serif; + + -moz-box-sizing : border-box; + box-sizing : border-box; + + padding : 0.1em 2.5em 0.2em 0.5em; /* 1px 25px 2px 5px */ + width : 10em; /* 100px */ + + border : 0.2em solid #000; /* 2px */ + border-radius : 0.4em; /* 4px */ + + box-shadow : 0 0.1em 0.2em rgba(0,0,0,.45); /* 0 1px 2px */ + + background : #F0F0F0; + background : -webkit-linear-gradient(90deg, #E3E3E3, #fcfcfc 50%, #f0f0f0); + background : linear-gradient(0deg, #E3E3E3, #fcfcfc 50%, #f0f0f0); +} + +.select .value { + display : inline-block; + width : 100%; + overflow : hidden; + + white-space : nowrap; + text-overflow : ellipsis; + vertical-align: top; +} + +.select:after { + content : "▼"; + position: absolute; + z-index : 1; + height : 100%; + width : 2em; /* 20px */ + top : 0; + right : 0; + + padding-top : .1em; + + -moz-box-sizing : border-box; + box-sizing : border-box; + + text-align : center; + + border-left : .2em solid #000; + border-radius: 0 .1em .1em 0; + + background-color : #000; + color : #FFF; +} + +.select .optList { + z-index : 2; + + list-style: none; + margin : 0; + padding: 0; + + background: #f0f0f0; + border: .2em solid #000; + border-top-width : .1em; + border-radius: 0 0 .4em .4em; + + box-shadow: 0 .2em .4em rgba(0,0,0,.4); + + -moz-box-sizing : border-box; + box-sizing : border-box; + + min-width : 100%; + max-height: 10em; /* 100px */ + overflow-y: auto; + overflow-x: hidden; +} + +.select .option { + padding: .2em .3em; +} + +.select .highlight { + background: #000; + color: #FFFFFF; +}</pre> + +<h3 id="活动状态结果">活动状态结果</h3> + +<div>{{ EmbedLiveSample('Active_state', 120, 130) }}</div> + +<h2 id="Open_state" name="Open_state">展开状态</h2> + +<h3 id="Open_state_HTML" name="Open_state_HTML">HTML</h3> + +<pre class="brush:html"><div class="select active"> + <span class="value">Cherry</span> + <ul class="optList"> + <li class="option highlight">Cherry</li> + <li class="option">Lemon</li> + <li class="option">Banana</li> + <li class="option">Strawberry</li> + <li class="option">Apple</li> + </ul> +</div></pre> + +<h3 id="Open_state_CSS" name="Open_state_CSS">CSS</h3> + +<pre class="brush:css">/* --------------- */ +/* Required Styles */ +/* --------------- */ + +.select { + position: relative; + display : inline-block; +} + +.select.active, +.select:focus { + box-shadow: 0 0 3px 1px #227755; + outline: none; +} + +.select .optList { + position: absolute; + top : 100%; + left : 0; +} + +.select .optList.hidden { + max-height: 0; + visibility: hidden; +} + +/* ------------ */ +/* Fancy Styles */ +/* ------------ */ + +.select { + font-size : 0.625em; /* 10px */ + font-family : Verdana, Arial, sans-serif; + + -moz-box-sizing : border-box; + box-sizing : border-box; + + padding : 0.1em 2.5em 0.2em 0.5em; /* 1px 25px 2px 5px */ + width : 10em; /* 100px */ + + border : 0.2em solid #000; /* 2px */ + border-radius : 0.4em; /* 4px */ + + box-shadow : 0 0.1em 0.2em rgba(0, 0, 0, .45); /* 0 1px 2px */ + + background : #F0F0F0; + background : -webkit-linear-gradient(90deg, #E3E3E3, #fcfcfc 50%, #f0f0f0); + background : linear-gradient(0deg, #E3E3E3, #fcfcfc 50%, #f0f0f0); +} + +.select .value { + display : inline-block; + width : 100%; + overflow : hidden; + + white-space : nowrap; + text-overflow : ellipsis; + vertical-align: top; +} + +.select:after { + content : "▼"; + position: absolute; + z-index : 1; + height : 100%; + width : 2em; /* 20px */ + top : 0; + right : 0; + + padding-top : .1em; + + -moz-box-sizing : border-box; + box-sizing : border-box; + + text-align : center; + + border-left : .2em solid #000; + border-radius: 0 .1em .1em 0; + + background-color : #000; + color : #FFF; +} + +.select .optList { + z-index : 2; + + list-style: none; + margin : 0; + padding: 0; + + background: #f0f0f0; + border: .2em solid #000; + border-top-width : .1em; + border-radius: 0 0 .4em .4em; + + box-shadow: 0 .2em .4em rgba(0,0,0,.4); + + -moz-box-sizing : border-box; + box-sizing : border-box; + + min-width : 100%; + max-height: 10em; /* 100px */ + overflow-y: auto; + overflow-x: hidden; +} + +.select .option { + padding: .2em .3em; +} + +.select .highlight { + background: #000; + color: #FFF; +}</pre> + +<h3 id="展开状态结果">展开状态结果</h3> + +<div>{{ EmbedLiveSample('Open_state', 120, 130) }}</div> diff --git a/files/zh-cn/learn/html/forms/how_to_build_custom_form_widgets/example_2/index.html b/files/zh-cn/learn/html/forms/how_to_build_custom_form_widgets/example_2/index.html new file mode 100644 index 0000000000..3a9546631f --- /dev/null +++ b/files/zh-cn/learn/html/forms/how_to_build_custom_form_widgets/example_2/index.html @@ -0,0 +1,212 @@ +--- +title: Example 2 +slug: Learn/HTML/Forms/How_to_build_custom_form_widgets/Example_2 +tags: + - HTML + - 表单 +translation_of: Learn/Forms/How_to_build_custom_form_controls/Example_2 +--- +<p>这是解释 <a href="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets" title="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets">如何构建自定义表单小部件</a>的第二个示例。</p> + +<h2 id="JS" name="JS">使用JS</h2> + +<h3 id="HTML_内容">HTML 内容</h3> + +<pre class="brush: html"><form class="no-widget"> + <select name="myFruit"> + <option>Cherry</option> + <option>Lemon</option> + <option>Banana</option> + <option>Strawberry</option> + <option>Apple</option> + </select> + + <div class="select"> + <span class="value">Cherry</span> + <ul class="optList hidden"> + <li class="option">Cherry</li> + <li class="option">Lemon</li> + <li class="option">Banana</li> + <li class="option">Strawberry</li> + <li class="option">Apple</li> + </ul> + </div> +<form> +</pre> + +<h3 id="CSS_内容">CSS 内容</h3> + +<pre class="brush: css">.widget select, +.no-widget .select { + position : absolute; + left : -5000em; + height : 0; + overflow : hidden; +} + +/* --------------- */ +/* Required Styles */ +/* --------------- */ + +.select { + position: relative; + display : inline-block; +} + +.select.active, +.select:focus { + box-shadow: 0 0 3px 1px #227755; + outline: none; +} + +.select .optList { + position: absolute; + top : 100%; + left : 0; +} + +.select .optList.hidden { + max-height: 0; + visibility: hidden; +} + +/* ------------ */ +/* Fancy Styles */ +/* ------------ */ + +.select { + font-size : 0.625em; /* 10px */ + font-family : Verdana, Arial, sans-serif; + + -moz-box-sizing : border-box; + box-sizing : border-box; + + padding : 0.1em 2.5em 0.2em 0.5em; /* 1px 25px 2px 5px */ + width : 10em; /* 100px */ + + border : 0.2em solid #000; /* 2px */ + border-radius : 0.4em; /* 4px */ + + box-shadow : 0 0.1em 0.2em rgba(0,0,0,.45); /* 0 1px 2px */ + + background : #F0F0F0; + background : -webkit-linear-gradient(90deg, #E3E3E3, #fcfcfc 50%, #f0f0f0); + background : linear-gradient(0deg, #E3E3E3, #fcfcfc 50%, #f0f0f0); +} + +.select .value { + display : inline-block; + width : 100%; + overflow : hidden; + + white-space : nowrap; + text-overflow : ellipsis; + vertical-align: top; +} + +.select:after { + content : "▼"; + position: absolute; + z-index : 1; + height : 100%; + width : 2em; /* 20px */ + top : 0; + right : 0; + + padding-top : .1em; + + -moz-box-sizing : border-box; + box-sizing : border-box; + + text-align : center; + + border-left : .2em solid #000; + border-radius: 0 .1em .1em 0; + + background-color : #000; + color : #FFF; +} + +.select .optList { + z-index : 2; + + list-style: none; + margin : 0; + padding: 0; + + background: #f0f0f0; + border: .2em solid #000; + border-top-width : .1em; + border-radius: 0 0 .4em .4em; + + box-shadow: 0 .2em .4em rgba(0,0,0,.4); + + -moz-box-sizing : border-box; + box-sizing : border-box; + + min-width : 100%; + max-height: 10em; /* 100px */ + overflow-y: auto; + overflow-x: hidden; +} + +.select .option { + padding: .2em .3em; +} + +.select .highlight { + background: #000; + color: #FFFFFF; +}</pre> + +<h3 id="JavaScript_内容">JavaScript 内容</h3> + +<pre class="brush: js">window.addEventListener("load", function () { + var form = document.querySelector('form'); + + form.classList.remove("no-widget"); + form.classList.add("widget"); +});</pre> + +<h3 id="使用JS的结果">使用JS的结果</h3> + +<p>{{ EmbedLiveSample('JS', 120, 130) }}</p> + +<h2 id="No_JS" name="No_JS">不使用JS</h2> + +<h3 id="HTML_内容_2">HTML 内容</h3> + +<pre class="brush: html"><form class="no-widget"> + <select name="myFruit"> + <option>Cherry</option> + <option>Lemon</option> + <option>Banana</option> + <option>Strawberry</option> + <option>Apple</option> + </select> + + <div class="select"> + <span class="value">Cherry</span> + <ul class="optList hidden"> + <li class="option">Cherry</li> + <li class="option">Lemon</li> + <li class="option">Banana</li> + <li class="option">Strawberry</li> + <li class="option">Apple</li> + </ul> + </div> +<form></pre> + +<h3 id="CSS_内容_2">CSS 内容</h3> + +<pre class="brush: css">.widget select, +.no-widget .select { + position : absolute; + left : -5000em; + height : 0; + overflow : hidden; +}</pre> + +<h3 id="不使用JS的结果">不使用JS的结果</h3> + +<p>{{ EmbedLiveSample('No_JS', 120, 130) }}</p> diff --git a/files/zh-cn/learn/html/forms/how_to_build_custom_form_widgets/example_3/index.html b/files/zh-cn/learn/html/forms/how_to_build_custom_form_widgets/example_3/index.html new file mode 100644 index 0000000000..a4a58880e4 --- /dev/null +++ b/files/zh-cn/learn/html/forms/how_to_build_custom_form_widgets/example_3/index.html @@ -0,0 +1,246 @@ +--- +title: Example 3 +slug: Learn/HTML/Forms/How_to_build_custom_form_widgets/Example_3 +tags: + - HTML + - 表单 +translation_of: Learn/Forms/How_to_build_custom_form_controls/Example_3 +--- +<p>这是解释 <a href="https://developer.mozilla.org/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets" title="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets">如何构建自定义表单小部件</a> 的第三个示例。</p> + +<h2 id="Change_states" name="Change_states">Change states</h2> + +<h3 id="HTML_内容">HTML 内容</h3> + +<pre class="brush: html"><form class="no-widget"> + <select name="myFruit" tabindex="-1"> + <option>Cherry</option> + <option>Lemon</option> + <option>Banana</option> + <option>Strawberry</option> + <option>Apple</option> + </select> + + <div class="select" tabindex="0"> + <span class="value">Cherry</span> + <ul class="optList hidden"> + <li class="option">Cherry</li> + <li class="option">Lemon</li> + <li class="option">Banana</li> + <li class="option">Strawberry</li> + <li class="option">Apple</li> + </ul> + </div> +</form></pre> + +<h3 id="CSS_内容">CSS 内容</h3> + +<pre class="brush: css">.widget select, +.no-widget .select { + position : absolute; + left : -5000em; + height : 0; + overflow : hidden; +} + +/* --------------- */ +/* Required Styles */ +/* --------------- */ + +.select { + position: relative; + display : inline-block; +} + +.select.active, +.select:focus { + box-shadow: 0 0 3px 1px #227755; + outline: none; +} + +.select .optList { + position: absolute; + top : 100%; + left : 0; +} + +.select .optList.hidden { + max-height: 0; + visibility: hidden; +} + +/* ------------ */ +/* Fancy Styles */ +/* ------------ */ + +.select { + font-size : 0.625em; /* 10px */ + font-family : Verdana, Arial, sans-serif; + + -moz-box-sizing : border-box; + box-sizing : border-box; + + padding : 0.1em 2.5em 0.2em 0.5em; /* 1px 25px 2px 5px */ + width : 10em; /* 100px */ + + border : 0.2em solid #000; /* 2px */ + border-radius : 0.4em; /* 4px */ + + box-shadow : 0 0.1em 0.2em rgba(0,0,0,.45); /* 0 1px 2px */ + + background : #F0F0F0; + background : -webkit-linear-gradient(90deg, #E3E3E3, #fcfcfc 50%, #f0f0f0); + background : linear-gradient(0deg, #E3E3E3, #fcfcfc 50%, #f0f0f0); +} + +.select .value { + display : inline-block; + width : 100%; + overflow : hidden; + + white-space : nowrap; + text-overflow : ellipsis; + vertical-align: top; +} + +.select:after { + content : "▼"; + position: absolute; + z-index : 1; + height : 100%; + width : 2em; /* 20px */ + top : 0; + right : 0; + + padding-top : .1em; + + -moz-box-sizing : border-box; + box-sizing : border-box; + + text-align : center; + + border-left : .2em solid #000; + border-radius: 0 .1em .1em 0; + + background-color : #000; + color : #FFF; +} + +.select .optList { + z-index : 2; + + list-style: none; + margin : 0; + padding: 0; + + background: #f0f0f0; + border: .2em solid #000; + border-top-width : .1em; + border-radius: 0 0 .4em .4em; + + box-shadow: 0 .2em .4em rgba(0,0,0,.4); + + -moz-box-sizing : border-box; + box-sizing : border-box; + + min-width : 100%; + max-height: 10em; /* 100px */ + overflow-y: auto; + overflow-x: hidden; +} + +.select .option { + padding: .2em .3em; +} + +.select .highlight { + background: #000; + color: #FFFFFF; +}</pre> + +<h3 id="JavaScript_内容">JavaScript 内容</h3> + +<pre class="brush: js">// ------- // +// HELPERS // +// ------- // + +NodeList.prototype.forEach = function (callback) { + Array.prototype.forEach.call(this, callback); +} + +// -------------------- // +// Function definitions // +// -------------------- // + +function deactivateSelect(select) { + if (!select.classList.contains('active')) return; + + var optList = select.querySelector('.optList'); + + optList.classList.add('hidden'); + select.classList.remove('active'); +} + +function activeSelect(select, selectList) { + if (select.classList.contains('active')) return; + + selectList.forEach(deactivateSelect); + select.classList.add('active'); +}; + +function toggleOptList(select, show) { + var optList = select.querySelector('.optList'); + + optList.classList.toggle('hidden'); +} + +function highlightOption(select, option) { + var optionList = select.querySelectorAll('.option'); + + optionList.forEach(function (other) { + other.classList.remove('highlight'); + }); + + option.classList.add('highlight'); +}; + +// ------------- // +// Event binding // +// ------------- // + +window.addEventListener("load", function () { + var form = document.querySelector('form'); + + form.classList.remove("no-widget"); + form.classList.add("widget"); +}); + +window.addEventListener('load', function () { + var selectList = document.querySelectorAll('.select'); + + selectList.forEach(function (select) { + var optionList = select.querySelectorAll('.option'); + + optionList.forEach(function (option) { + option.addEventListener('mouseover', function () { + highlightOption(select, option); + }); + }); + + select.addEventListener('click', function (event) { + toggleOptList(select); + }, false); + + select.addEventListener('focus', function (event) { + activeSelect(select, selectList); + }); + + select.addEventListener('blur', function (event) { + deactivateSelect(select); + }); + }); +});</pre> + +<h3 id="结果">结果</h3> + +<p>{{ EmbedLiveSample('Change_states') }}</p> diff --git a/files/zh-cn/learn/html/forms/how_to_build_custom_form_widgets/example_4/index.html b/files/zh-cn/learn/html/forms/how_to_build_custom_form_widgets/example_4/index.html new file mode 100644 index 0000000000..472102adb2 --- /dev/null +++ b/files/zh-cn/learn/html/forms/how_to_build_custom_form_widgets/example_4/index.html @@ -0,0 +1,294 @@ +--- +title: Example 4 +slug: Learn/HTML/Forms/How_to_build_custom_form_widgets/Example_4 +tags: + - HTML + - Web + - 表单 + - 高级 +translation_of: Learn/Forms/How_to_build_custom_form_controls/Example_4 +--- +<p>这是解释 <a href="/en-US/docs/Learn/HTML/Forms/How_to_build_custom_form_widgets">如何构建自定义表单小部件</a> 的第四个示例。</p> + +<h2 id="Change_states" name="Change_states">改变状态</h2> + +<h3 id="HTML_内容">HTML 内容</h3> + +<pre class="brush: html"><form class="no-widget"> + <select name="myFruit"> + <option>Cherry</option> + <option>Lemon</option> + <option>Banana</option> + <option>Strawberry</option> + <option>Apple</option> + </select> + + <div class="select"> + <span class="value">Cherry</span> + <ul class="optList hidden"> + <li class="option">Cherry</li> + <li class="option">Lemon</li> + <li class="option">Banana</li> + <li class="option">Strawberry</li> + <li class="option">Apple</li> + </ul> + </div> +</form></pre> + +<h3 id="CSS_内容">CSS 内容</h3> + +<pre class="brush: css">.widget select, +.no-widget .select { + position : absolute; + left : -5000em; + height : 0; + overflow : hidden; +} + +/* --------------- */ +/* Required Styles */ +/* --------------- */ + +.select { + position: relative; + display : inline-block; +} + +.select.active, +.select:focus { + box-shadow: 0 0 3px 1px #227755; + outline: none; +} + +.select .optList { + position: absolute; + top : 100%; + left : 0; +} + +.select .optList.hidden { + max-height: 0; + visibility: hidden; +} + +/* ------------ */ +/* Fancy Styles */ +/* ------------ */ + +.select { + font-size : 0.625em; /* 10px */ + font-family : Verdana, Arial, sans-serif; + + -moz-box-sizing : border-box; + box-sizing : border-box; + + padding : 0.1em 2.5em 0.2em 0.5em; /* 1px 25px 2px 5px */ + width : 10em; /* 100px */ + + border : 0.2em solid #000; /* 2px */ + border-radius : 0.4em; /* 4px */ + + box-shadow : 0 0.1em 0.2em rgba(0,0,0,.45); /* 0 1px 2px */ + + background : #F0F0F0; + background : -webkit-linear-gradient(90deg, #E3E3E3, #fcfcfc 50%, #f0f0f0); + background : linear-gradient(0deg, #E3E3E3, #fcfcfc 50%, #f0f0f0); +} + +.select .value { + display : inline-block; + width : 100%; + overflow : hidden; + + white-space : nowrap; + text-overflow : ellipsis; + vertical-align: top; +} + +.select:after { + content : "▼"; + position: absolute; + z-index : 1; + height : 100%; + width : 2em; /* 20px */ + top : 0; + right : 0; + + padding-top : .1em; + + -moz-box-sizing : border-box; + box-sizing : border-box; + + text-align : center; + + border-left : .2em solid #000; + border-radius: 0 .1em .1em 0; + + background-color : #000; + color : #FFF; +} + +.select .optList { + z-index : 2; + + list-style: none; + margin : 0; + padding: 0; + + background: #f0f0f0; + border: .2em solid #000; + border-top-width : .1em; + border-radius: 0 0 .4em .4em; + + box-shadow: 0 .2em .4em rgba(0,0,0,.4); + + -moz-box-sizing : border-box; + box-sizing : border-box; + + min-width : 100%; + max-height: 10em; /* 100px */ + overflow-y: auto; + overflow-x: hidden; +} + +.select .option { + padding: .2em .3em; +} + +.select .highlight { + background: #000; + color: #FFFFFF; +}</pre> + +<h3 id="JavaScript_内容">JavaScript 内容</h3> + +<pre class="brush: js">// ------- // +// HELPERS // +// ------- // + +NodeList.prototype.forEach = function (callback) { + Array.prototype.forEach.call(this, callback); +} + +// -------------------- // +// Function definitions // +// -------------------- // + +function deactivateSelect(select) { + if (!select.classList.contains('active')) return; + + var optList = select.querySelector('.optList'); + + optList.classList.add('hidden'); + select.classList.remove('active'); +} + +function activeSelect(select, selectList) { + if (select.classList.contains('active')) return; + + selectList.forEach(deactivateSelect); + select.classList.add('active'); +}; + +function toggleOptList(select, show) { + var optList = select.querySelector('.optList'); + + optList.classList.toggle('hidden'); +} + +function highlightOption(select, option) { + var optionList = select.querySelectorAll('.option'); + + optionList.forEach(function (other) { + other.classList.remove('highlight'); + }); + + option.classList.add('highlight'); +}; + +function updateValue(select, index) { + var nativeWidget = select.previousElementSibling; + var value = select.querySelector('.value'); + var optionList = select.querySelectorAll('.option'); + + nativeWidget.selectedIndex = index; + value.innerHTML = optionList[index].innerHTML; + highlightOption(select, optionList[index]); +}; + +function getIndex(select) { + var nativeWidget = select.previousElementSibling; + + return nativeWidget.selectedIndex; +}; + +// ------------- // +// Event binding // +// ------------- // + +window.addEventListener("load", function () { + var form = document.querySelector('form'); + + form.classList.remove("no-widget"); + form.classList.add("widget"); +}); + +window.addEventListener('load', function () { + var selectList = document.querySelectorAll('.select'); + + selectList.forEach(function (select) { + var optionList = select.querySelectorAll('.option'); + + optionList.forEach(function (option) { + option.addEventListener('mouseover', function () { + highlightOption(select, option); + }); + }); + + select.addEventListener('click', function (event) { + toggleOptList(select); + }); + + select.addEventListener('focus', function (event) { + activeSelect(select, selectList); + }); + + select.addEventListener('blur', function (event) { + deactivateSelect(select); + }); + }); +}); + +window.addEventListener('load', function () { + var selectList = document.querySelectorAll('.select'); + + selectList.forEach(function (select) { + var optionList = select.querySelectorAll('.option'), + selectedIndex = getIndex(select); + + select.tabIndex = 0; + select.previousElementSibling.tabIndex = -1; + + updateValue(select, selectedIndex); + + optionList.forEach(function (option, index) { + option.addEventListener('click', function (event) { + updateValue(select, index); + }); + }); + + select.addEventListener('keyup', function (event) { + var length = optionList.length, + index = getIndex(select); + + if (event.keyCode === 40 && index < length - 1) { index++; } + if (event.keyCode === 38 && index > 0) { index--; } + + updateValue(select, index); + }); + }); +});</pre> + +<h3 id="结果">结果</h3> + +<p>{{ EmbedLiveSample('Change_states') }}</p> diff --git a/files/zh-cn/learn/html/forms/how_to_build_custom_form_widgets/index.html b/files/zh-cn/learn/html/forms/how_to_build_custom_form_widgets/index.html new file mode 100644 index 0000000000..24636e7858 --- /dev/null +++ b/files/zh-cn/learn/html/forms/how_to_build_custom_form_widgets/index.html @@ -0,0 +1,776 @@ +--- +title: 如何构建表单小工具 +slug: Learn/HTML/Forms/How_to_build_custom_form_widgets +tags: + - HTML + - 例子 + - 表单 + - 高级 +translation_of: Learn/Forms/How_to_build_custom_form_controls +--- +<div>{{LearnSidebar}}{{PreviousMenuNext("Learn/HTML/Forms/Form_validation", "Learn/HTML/Forms/Sending_forms_through_JavaScript", "Learn/HTML/Forms")}}</div> + +<p class="summary">在许多情况下,<a href="/en-US/docs/HTML/Forms/The_native_form_widgets" title="/en-US/docs/HTML/Forms/The_native_form_widgets">可用的 HTML 表单小组件</a><em>是不够的</em>。如果要在某些小部件(例如 {{HTMLElement("select")}}元素)上执行<a href="/en-US/docs/Advanced_styling_for_HTML_forms" title="/en-US/docs/Advanced_styling_for_HTML_forms">高级样式</a>,或者如果要提供自定义表现,则别无选择,只能构建自己的小部件。</p> + +<p>在本文中,我们会看到如何构建这样的组件。为此,我们将使用这样一个例子:重建 {{HTMLElement("select")}}元素。</p> + +<div class="note"> +<p><strong>注意:</strong> 我们将专注于构建小部件,而不是怎样让代码更通用或可复用;那会涉及一些非基础的JavaScript代码和未知环境下的DOM操作,这超过了这篇文章的范围。</p> +</div> + +<h2 id="设计_结构_和语义">设计, 结构, 和语义</h2> + +<p>在构建一个自定义控件之前,首先你要确切的知道你要什么。 这将为您节省宝贵的时间。 特别地,清楚地定义控件的所有状态非常重要。 为了做到这一点,从状态和行为表现都众所周知的现有小控件开始是很好的选择,这样你可以轻松的尽量模仿这些控件。</p> + +<p>在我们的示例中,我们将重建HTML<select>元素,这是我们希望实现的结果:</p> + +<p><img alt="The three states of a select box" src="/files/4481/custom-select.png" style="height: 135px; width: 366px;"></p> + +<p>上面图片显示了我们控件的三个主要状态:正常状态(左); 活动状态(中)和打开状态(右)。</p> + +<p>在行为方面,我们希望我们的控件像任何原生控件一样对鼠标和键盘都可用。 让我们从定义控件如何到达每个状态开始:</p> + +<dl> + <dt>以下情况控件将会呈现正常状态:</dt> + <dd> + <ul> + <li>页面加载</li> + <li>控件处于活动状态,但用户点击控件以外的任何位置</li> + <li>控件是活动状态,但用户使用键盘将焦点移动到另一个小部件</li> + </ul> + + <div class="note"> + <p><strong>注意:</strong> 在页面上移动焦点通常是通过按Tab键来完成的,但这并不是哪都通用的标准。 例如,在Safari中页面上的链接间的循环切换默认下是通过使用<a href="http://www.456bereastreet.com/archive/200906/enabling_keyboard_navigation_in_mac_os_x_web_browsers/">组合键Option + Tab</a>完成的。</p> + </div> + </dd> + <dt>以下情况控件将会呈现活动状态:</dt> + <dd> + <ul> + <li>用户点击</li> + <li>用户按下tab让控件获得了焦点。</li> + <li>控件呈现打开状态然后用户点击控件。</li> + </ul> + </dd> + <dt>以下情况控件将会呈现打开状态:</dt> + <dd> + <ul> + <li>控件在非打开状态时被用户点击。</li> + </ul> + </dd> +</dl> + +<p>我们知道如何改变状态后,定义如何改变小工具的值还很重要:</p> + +<dl> + <dt>以下情况控件的值将会被改变:</dt> + <dd> + <ul> + <li>控件在打开状态下用户点击一个选项</li> + <li>控件在活动状态下用户按下键盘上方向键或者下方向键</li> + </ul> + </dd> +</dl> + +<p>最后,让我们定义控件的选项将要怎么表现:</p> + +<ul> + <li>当控件在打开状态时,被选中的选项将被突出显示</li> + <li>当鼠标悬停在某个选项上时,该选项将被突出显示,并且之前突出显示的选项将返回正常的状态</li> +</ul> + +<p>对于我们的例子的目的,我们将就此结束;但是,如果你是一个认真的读者,你会注意到我们省略了一些东西,例如,你认为用户在小部件处于打开状态时点击tab键会发生什么?答案是:什么也不会发生。好吧,似乎很明显这就是正确的行为,但事实是,因为在我们的规范中没有定义这种情况,我们很容易忽略这种行为。在团队环境中尤其是这样,因为设计小部件行为的人与实现的人通常是不同的。</p> + +<p>另外一个有趣的例子是:当小部件处于打开状态时,用户按下键盘上方向键和下方向键将会发生什么?这个问题有些棘手,如果你认为活动状态和打开状态是完全不同的,那么答案就是“什么都不会发生”,因为我们没有定义任何在打开状态下键盘的交互行为。从另一个方面看,如果你认为活动状态和打开状态是有重叠的部分,那么控件的值可能会改变,但是被选中的选项肯定不会相应的进行突出显示,同样是因为我们没有定义在控件打开状态下的任何键盘交互事件(我们仅仅定义了控件打开会发生什么,而没有定义在其打开后会发生什么)</p> + +<p>在我们的例子中,缺失的规范是显而易见的,所以我们将着手处理他们,但是对于一些没有人想到去定义正确行为的小部件而言,这的确是一个问题。所以在设计阶段花费时间是值得的,因为如果你定义的行为不够好,或者忘记定义了一个行为,那么在用户开始实际使用时,将会很难去重新定义它们。如果你在定义时有疑问,请征询他人的意见,如果你有预算,请不要犹豫的去进行<a href="https://en.wikipedia.org/wiki/Usability_testing">用户可行性测试</a>,这个过程被称为UX design (User Experience <em>Design</em>用户体验设计),如果你想要深入的学习相关的内容,请查阅下面这些有用资源:</p> + +<ul> + <li><a href="http://www.uxmatters.com/" rel="external" title="http://www.uxmatters.com/">UXMatters.com</a></li> + <li><a href="http://uxdesign.com/" rel="external" title="http://uxdesign.com/">UXDesign.com</a></li> + <li><a href="http://uxdesign.smashingmagazine.com/" rel="external" title="http://uxdesign.smashingmagazine.com/">The UX Design section of SmashingMagazine</a></li> +</ul> + +<div class="note"> +<p><strong>注意: </strong>另外, 在绝大多数系统中,还有一种方法能够打开{{HTMLElement("select")}}元素来观察其所有的选项(这和用鼠标点击{{HTMLElement("select")}}元素是一样的)。通过Windows下的Alt + 向下箭头实现,在我们的例子中没有实现---但是这样做会很方便,因为鼠标点击事件就是由该原理实现的。</p> +</div> + +<h3 id="定义语义化的_HTML_结构">定义语义化的 HTML 结构</h3> + +<p>现在控件的基本功能已经决定了,可以开始构建自定义控件了。第一步是要确定 HTML 结构并给予一些基本的语义规则。第一步就是去确定它的HTML结构并给予一些基本的语义。重构{{HTMLElement("select")}}元素需要怎么做如下:</p> + +<pre class="brush: html"><!-- 这是我们小部件的主要容器. + tabindex属性是用来让用户聚焦在小部件上的. + 稍后我们会发现最好通过JavaScript来设定它的值. --> +<div class="select" tabindex="0"> + + <!-- 这个容器用来显示组件现在的值 --> + <span class="value">Cherry</span> + + <!-- 这个容器包含我们的组件的所有可用选项. + 因为他是一个列表,用ul元素是有意义的. --> + <ul class="optList"> + <!-- 每个选项只包含用来显示的值, + 稍后我们会知道如何处理和表单一起发送的真实值 --> + <li class="option">Cherry</li> + <li class="option">Lemon</li> + <li class="option">Banana</li> + <li class="option">Strawberry</li> + <li class="option">Apple</li> + </ul> + +</div></pre> + +<p>注意类名的使用:不管实际使用了哪种底层HTML元素,它们都标识每个相关的部分。这很重要,因为这样做能确保我们的CSS和JavaScript不会和HTML结构强绑定,这样我们就可以在不破坏使用小部件的代码的情况下进行实现更改。比如,如果你希望增加一个等价的{{HTMLElement("optgroup")}}元素。</p> + +<h3 id="使用_CSS_创建外观">使用 CSS 创建外观</h3> + +<p>现在我们有了控件结构,我们可以开始设计我们的控件了。构建自定义控件的重点是能够完全按照我们的期望设置它的样式。为了达到这个目的,我们将 CSS部分的工作分为两部分:第一部分是让我们的控件表现得像一个{{HTMLElement("select")}}元素所必需的的CSS规则,第二部分包含了让组件看起来像我们所希望那样的精妙样式。</p> + +<h4 id="所需的样式">所需的样式</h4> + +<p>所需的样式是那些用以处理我们组件的三种状态的必须样式。</p> + +<pre class="brush: css">.select { + /* 这将为选项列表创建一个上下文定位 */ + position: relative; + + /* 这将使我们的组件成为文本流的一部分,同时又可以调整大小 */ + display : inline-block; +}</pre> + +<p>我们需要一个额外的类 <code>active</code> 来定义我们的组件处于其激活状态时的的界面外观。因为我们的组件是可以聚焦的, 我们通过{{cssxref(":focus")}} 伪类重复自定义样式来确保它们表现得一样。</p> + +<pre class="brush: css">.select .active, +.select:focus { + outline: none; + + /* 这里的 box-shadow 属性并非必须,但确保活动状态能看出来非常重要---我们 + 将其作为一个默认值,你可以随意地覆盖掉它. */ + box-shadow: 0 0 3px 1px #227755; +}</pre> + +<p>现在,让我们处理选项列表:</p> + +<pre class="brush: css">/* 这里的 .select 选择器是一个糖衣语法,用来确保我们定义的类是 + 在我们的组件里的那个。 */ +.select .optList { + /* 这可以确保我们的选项列表将会显示在值的下面,并且会处在 + HTML 流之外*/ + position : absolute; + top : 100%; + left : 0; +}</pre> + +<p>我们需要一个额外的类来处理选项列表隐藏时的情况。为了管理没有完全匹配的活动状态和打开状态之间的差异,这是有必要的。</p> + +<pre class="brush: css">.select .optList.hidden { + /* 这是一个以可访问形式隐藏列表的简单方法, + 对可访问性我们将在最后进一步拓展 */ + max-height: 0; + visibility: hidden; +}</pre> + +<h4 id="美化">美化</h4> + +<p>所以现在我们的基本功能已经就位,有趣的事情就可以开始了。下面是一个可行的简单的例子,和本文开头的截图是相对应的。不管怎样,你可以随意的体验一下看看能收获什么。</p> + +<pre class="brush: css">.select { + /* 出于可访问性方面的原因,所有尺寸都会由em值表示 + (用来确保用户在文本模式下使用浏览器缩放时组件的可缩放性). + 在大多数浏览器下的默认换算是1em == 16px. + 如果你对em和px的转换感到疑惑, 请参考http://riddle.pl/emcalc/ */ + font-size : 0.625em; /* 这个(=10px)是以em方式表达的这个环境里的字体大小 */ + font-family : Verdana, Arial, sans-serif; + + -moz-box-sizing : border-box; + box-sizing : border-box; + + /* 我们需要为将要添加的向下箭头准备一些额外的空间 */ + padding : .1em 2.5em .2em .5em; /* 1px 25px 2px 5px */ + width : 10em; /* 100px */ + + border : .2em solid #000; /* 2px */ + border-radius : .4em; /* 4px */ + box-shadow : 0 .1em .2em rgba(0,0,0,.45); /* 0 1px 2px */ + + /* 第一段声明是为了不支持线性梯度填充的浏览器准备的。 + 第二段声明是因为基于WebKit的浏览器没有预先定义它。 + 如果你想为过时的浏览器提供支持, 请参阅 http://www.colorzilla.com/gradient-editor/ */ + background : #F0F0F0; + background : -webkit-linear-gradient(90deg, #E3E3E3, #fcfcfc 50%, #f0f0f0); + background : linear-gradient(0deg, #E3E3E3, #fcfcfc 50%, #f0f0f0); +} + +.select .value { + /* 因为值的宽度可能超过组件的宽度,我们需要确保他不会改变组件的宽度 */ + display : inline-block; + width : 100%; + overflow : hidden; + + vertical-align: top; + + /* 如果内容溢出了, 最好有一个恰当的缩写. */ + white-space : nowrap; + text-overflow: ellipsis; +}</pre> + +<p>我们不需要一个额外的元素来设计向下的箭头,而使用{{cssxref(":after")}} 伪类来替代。然而,这也可以通过使用一张加在<code>select</code> class上的简单的背景图像来实现。</p> + +<pre class="brush: css">.select:after { + content : "▼"; /* 我们使用了unicode 编码的字符 U+25BC; 参阅 http://www.utf8-chartable.de */ + position: absolute; + z-index : 1; /* 这对于防止箭头覆盖选项列表很重要 */ + top : 0; + right : 0; + + -moz-box-sizing : border-box; + box-sizing : border-box; + + height : 100%; + width : 2em; /* 20px */ + padding-top : .1em; /* 1px */ + + border-left : .2em solid #000; /* 2px */ + border-radius: 0 .1em .1em 0; /* 0 1px 1px 0 */ + + background-color : #000; + color : #FFF; + text-align : center; +}</pre> + +<p>接下来,让我们定义选项列表的样式。</p> + +<pre class="brush: css">.select .optList { + z-index : 2; /* 我们明确的表示选项列表会始终与向下箭头重叠 */ + + /* 这会重置ul元素的默认样式 */ + list-style: none; + margin : 0; + padding: 0; + + -moz-box-sizing : border-box; + box-sizing : border-box; + + /* 这会确保即使数值比组件小,选项列表仍能变得跟组件自身一样大*/ + min-width : 100%; + + /* 万一列表太长了, 它的内容会从垂直方向溢出(会自动添加一个竖向滚动条) + 但是水平方向不会(因为我们没有设定宽度, 列表会自适应宽度. 如果不能的话,内容会被截断) */ + max-height: 10em; /* 100px */ + overflow-y: auto; + overflow-x: hidden; + + border: .2em solid #000; /* 2px */ + border-top-width : .1em; /* 1px */ + border-radius: 0 0 .4em .4em; /* 0 0 4px 4px */ + + box-shadow: 0 .2em .4em rgba(0,0,0,.4); /* 0 2px 4px */ + background: #f0f0f0; +}</pre> + +<p>对于选项,我们需要添加一个 <code>highlight</code> 类以便能标明用户将要选择的值或者已经选择的值。</p> + +<pre class="brush: css">.select .option { + padding: .2em .3em; /* 2px 3px */ +} + +.select .highlight { + background: #000; + color: #FFFFFF; +}</pre> + +<p>这是三种状态的结果:</p> + +<table> + <thead> + <tr> + <th scope="col" style="text-align: center;">基本状态</th> + <th scope="col" style="text-align: center;">活动状态</th> + <th scope="col" style="text-align: center;">打开状态</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{EmbedLiveSample("Basic_state",120,130, "", "/Learn/HTML/Forms/How_to_build_custom_form_widgets/Example_1")}}</td> + <td>{{EmbedLiveSample("Active_state",120,130, "", "/Learn/HTML/Forms/How_to_build_custom_form_widgets/Example_1")}}</td> + <td>{{EmbedLiveSample("Open_state",120,130, "", "/Learn/HTML/Forms/How_to_build_custom_form_widgets/Example_1")}}</td> + </tr> + <tr> + <td colspan="3" style="text-align: center;"><a href="/zh-CN/docs/Learn/HTML/Forms/How_to_build_custom_form_widgets/Example_1" title="/zh-CN/docs/Learn/HTML/Forms/How_to_build_custom_form_widgets/Example_1">Check out the source code</a></td> + </tr> + </tbody> +</table> + +<h2 id="通过JavaScript让您的小部件动起来">通过JavaScript让您的小部件动起来</h2> + +<p>现在我们的设计和结构已经完成了。我们可以写些JavaScript代码来让这个部件真正生效。</p> + +<div class="warning"> +<p><strong>警告:</strong>下面的代码仅仅是教学性质的,并且不应该照搬使用。在许多方面,正如我们所看到的,这种方案不具有前瞻性,而且可能在旧浏览器上会不工作。这里面还有冗余的部分,在生产环境下,代码需要优化。</p> +</div> + +<div class="note"> +<p><strong>注意:</strong>创建可复用的组件可能是一件需要些技巧的事情。<a href="http://dvcs.w3.org/hg/webcomponents/raw-file/tip/explainer/index.html" rel="external" title="http://dvcs.w3.org/hg/webcomponents/raw-file/tip/explainer/index.html">W3C 网络组件草案</a> 是对这类特定问题的答案之一。<a href="http://x-tags.org/" rel="external" title="http://x-tags.org/">X-Tag 项目 </a>是对这一规格的实验性实现;我们建议你看看它。</p> +</div> + +<h3 id="它为什么不生效?">它为什么不生效?</h3> + +<p>在我们开始之前,要记住一件和 JavaScript 有关的非常重要的事情:在浏览器中,<strong>这是一种不可靠的技术。</strong>当你构建一个自定义组件时,你会不得不得依赖于<strong> </strong>JavaScript,因为这是将所有的东西联系在一起的线索。但是,很多情况下,JavaScript 不能在浏览器中运行。</p> + +<ul> + <li>用户关掉了 JavaScript: 这是最不常见的情形。现在只有很少的人会关掉 JavaScript。</li> + <li>脚本没有加载。这是最常见的情形,特别是在移动端上,在那些网络非常不可靠的地方。</li> + <li>脚本是有问题的。你应该总是考虑这种可能性。</li> + <li>脚本和第三方脚本冲突。这可能会由用户使用的跟踪脚本和一些书签工具引发。</li> + <li>脚本与一个浏览器的拓展冲突,或者受其影响。 (比如 Firefox 的 <a href="https://addons.mozilla.org/fr/firefox/addon/noscript/" rel="external" title="https://addons.mozilla.org/fr/firefox/addon/noscript/">NoScript</a> 拓展 或者 Chrome 的 <a href="https://chrome.google.com/webstore/detail/notscripts/odjhifogjcknibkahlpidmdajjpkkcfn" rel="external" title="https://chrome.google.com/webstore/detail/notscripts/odjhifogjcknibkahlpidmdajjpkkcfn">NotScripts</a> 拓展)。</li> + <li>用户在使用老旧的浏览器,而且你需要的一些功能没有被支持。当你使用一些最新的 API 时,这种情况会经常发生。</li> +</ul> + +<p>因为这些风险,认真考虑 JavaScript 不生效时会发生什么是很重要的。处理这个问题的细节超出了这篇文章的范围,因为这与你有多么想使你的脚本具有通用性和可复用性更加相关,不过我们将在我们的例子中考虑与其相关的基本内容。</p> + +<p>在我们的例子中,如果JavaScript代码没有运行,我们会回退到显示一个标准的 {{HTMLElement("select")}} 元素。为了实现这一点,我们需要两样东西。</p> + +<p>首先,在每次使用我们的自定义部件前,我们需要添加一个标准的 {{HTMLElement("select")}} 元素。实际上,为了能将来自我们自定义的表单组件和以及其他部分的表单数据发送出去,这个元素也是需要的。我们随后会详细的解释这一点。</p> + +<pre class="brush: html"><body class="no-widget"> + <form> + <select name="myFruit"> + <option>Cherry</option> + <option>Lemon</option> + <option>Banana</option> + <option>Strawberry</option> + <option>Apple</option> + </select> + + <div class="select"> + <span class="value">Cherry</span> + <ul class="optList hidden"> + <li class="option">Cherry</li> + <li class="option">Lemon</li> + <li class="option">Banana</li> + <li class="option">Strawberry</li> + <li class="option">Apple</li> + </ul> + </div> + </form> + +</body></pre> + +<p>第二,我们需要两个新的 classes 来隐藏不需要的元素(即,当我们的脚本没有运行时的自定义组件, 或是脚本正常运行时的"真正的" {{HTMLElement("select")}} 元素)。注意默认情况下,我们的 HTML 代码会隐藏我们的自定义组件。</p> + +<pre class="brush: css">.widget select, +.no-widget .select { + /* 这个CSS选择器大体上说的是: + - 要么我们将body的class设置为"widget",隐藏真实的{{HTMLElement("select")}}元素 + - 或是我们没有改变body的class,这样body的class还是"no-widget", + 因此class为"select"的元素需要被隐藏 */ + position : absolute; + left : -5000em; + height : 0; + overflow : hidden; +}</pre> + +<p>接下来我们需要一个 JavaScript 开关来决定脚本是否运行。这个开关非常简单:如果页面加载时,我们的脚本运行了,它将会移除 <code>no-widget</code> class ,并添加 <code>widget</code> class,由此切换 {{HTMLElement("select")}} 元素和自定义组件的可视性。</p> + +<pre class="brush: js">window.addEventListener("load", function () { + document.body.classList.remove("no-widget"); + document.body.classList.add("widget"); +});</pre> + +<table> + <thead> + <tr> + <th scope="col" style="text-align: center;">无 JS</th> + <th scope="col" style="text-align: center;">有 JS</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{EmbedLiveSample("No_JS",120,130, "", "/Learn/HTML/Forms/How_to_build_custom_form_widgets/Example_2")}}</td> + <td>{{EmbedLiveSample("JS",120,130, "", "/Learn/HTML/Forms/How_to_build_custom_form_widgets/Example_2")}}</td> + </tr> + <tr> + <td colspan="2" style="text-align: center;"><a href="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets/Example_2" title="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets/Example_2">Check out the source code</a></td> + </tr> + </tbody> +</table> + +<div class="note"> +<p><strong>注意:</strong> 如果你真的想让你的代码变得通用和可重用,最好不要做一个 class 选择器开关,而是通过添加一个组件 class 的方式来隐藏{{HTMLElement("select")}} 元素,并且动态地在每一个{{HTMLElement("select")}} 元素后面添加代表页面中自定义组件的 DOM 树。</p> +</div> + +<h3 id="让工作变得更简单">让工作变得更简单</h3> + +<p>在我们将要构建的代码之中,我们将会使用标准的 DOM API 来完成我们所要做的所有工作。尽管 DOM API 在浏览器中得到了更好支持,但是在旧的浏览器上还是会出现问题。( 特别是非常老的 Internet Explorer)。</p> + +<p>如果你想要避免旧浏览器带来的麻烦,这儿有两种解决方案:使用专门的框架,比如 <a href="http://jquery.com/" rel="external" title="http://jquery.com/">jQuery</a>, <a href="https://github.com/julienw/dollardom" rel="external" title="https://github.com/julienw/dollardom">$dom</a>, <a href="http://prototypejs.org/" rel="external" title="http://prototypejs.org/">prototype</a>, <a href="http://dojotoolkit.org/" rel="external" title="http://dojotoolkit.org/">Dojo</a>, <a href="http://yuilibrary.com/" rel="external" title="http://yuilibrary.com/">YUI</a>, 或者类似的框架,或者通过填充你想使用的缺失的特性 (这可以通过条件加载轻松完成——例如使用 <a href="http://yepnopejs.com/" rel="external" title="http://yepnopejs.com/">yepnope</a> 这样的库。</p> + +<p>我们打算使用的特性如下所示(按照风险程度从高到低排列):</p> + +<ol> + <li>{{domxref("element.classList","classList")}}</li> + <li>{{domxref("EventTarget.addEventListener","addEventListener")}}</li> + <li><code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach" title="/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach">forEach</a></code> (这不是 DOM而是现代 JavaScript )</li> + <li>{{domxref("element.querySelector","querySelector")}} 和 {{domxref("element.querySelectorAll","querySelectorAll")}}</li> +</ol> + +<p>除了那些特定特性的的可用性以外,在开始之前,仍然存在一个问题。由函数{{domxref("element.querySelectorAll","querySelectorAll()")}} 返回的对象是一个{{domxref("NodeList")}} 而不是 <code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Array" title="/en-US/docs/JavaScript/Reference/Global_Objects/Array">Array</a></code>。这一点非常重要,因为 <code>Array</code> 对象支持 <code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach" title="/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach">forEach</a></code> 函数,但是 {{domxref("NodeList")}} 不支持。由于 {{domxref("NodeList")}} 看起来实在是像一个 <code>Array</code> 并且因为 <code>forEach</code> 是这样的便于使用。我们可以轻易地添加对 {{domxref("NodeList")}}的支持,使我们的生活更轻松一些,像这样:</p> + +<pre class="brush: js">NodeList.prototype.forEach = function (callback) { + Array.prototype.forEach.call(this, callback); +}</pre> + +<p>我们没有开玩笑,这真的很容易实现。</p> + +<h3 id="构造事件回调">构造事件回调</h3> + +<p>基础已经准备好了,我们现在可以开始定义用户每次同我们的组件交互时会用到的所有函数了。</p> + +<pre class="brush: js">// 这个函数会用在每当我们想要停用一个自定义组件的时候 +// 它需要一个参数: +// select :要停用的带有 'select' 类的节点 +function deactivateSelect(select) { + + // 如果组件没有运行,不用进行任何操作 + if (!select.classList.contains('active')) return; + + // 我们需要获取自定义组件的选项列表 + var optList = select.querySelector('.optList'); + + // 关闭选项列表 + optList.classList.add('hidden'); + + // 然后停用组件本身 + select.classList.remove('active'); +} + +// 每当用户想要激活(或停用)这个组件的时候,会调用这个函数 +// 它需要2个参数: +// select : 要激活的带有'select'类的DOM节点 +// selectList : 包含所有带'select'类的DOM节点的列表 +function activeSelect(select, selectList) { + + // 如果组件已经激活了,不进行任何操作 + if (select.classList.contains('active')) return; + + // 我们需要关闭所有自定义组件的活动状态 + // 因为deactiveselect函数满足forEach回调函数的所有请求, + // 我们直接使用它,不使用中间匿名函数 + selectList.forEach(deactivateSelect); + + // 然后我们激活特定的组件 + select.classList.add('active'); +} + +// 每当用户想要打开/关闭选项列表的时候,会调用这个函数 +// 它需要一个参数: +// select : 要触发的列表的DOM节点 +function toggleOptList(select) { + + // 该列表不包含在组件中 + var optList = select.querySelector('.optList'); + + // 我们改变列表的class去显示/隐藏它 + optList.classList.toggle('hidden'); +} + +// 每当我们要高亮一个选项的时候,会调用该函数 +// 它需要两个参数: +// select : 带有'select'类的DOM节点,包含了需要高亮强调的选项 +// option : 需要高亮强调的带有'option'类的DOM节点 +function highlightOption(select, option) { + + // 为我们的自定义select元素获取所有有效选项的列表 + var optionList = select.querySelectorAll('.option'); + + // 我们移除所有选项的高亮强调 + optionList.forEach(function (other) { + other.classList.remove('highlight'); + }); + + // 我们高亮强调正确的选项 + option.classList.add('highlight'); +};</pre> + +<p>这是你需要用来处理组件不同状态的所有代码。</p> + +<p>接下来,我们将这些函数绑定到合适的事件上:</p> + +<pre class="brush: js">// 我们处理文档加载时的事件绑定。 +window.addEventListener('load', function () { + var selectList = document.querySelectorAll('.select'); + + // 每个自定义组件都需要初始化 + selectList.forEach(function (select) { + + // 它的'option'元素也需要 + var optionList = select.querySelectorAll('.option'); + + // 每当用户的鼠标悬停在一个选项上时,我们高亮这个指定的选项 + optionList.forEach(function (option) { + option.addEventListener('mouseover', function () { + // 注意:'select'和'option'变量是我们函数调用范围内有效的闭包 。 + highlightOption(select, option); + }); + }); + + // 每当用户点击一个自定义的select元素时 + select.addEventListener('click', function (event) { + // 注意:'select'变量是我们函数调用范围内有效的闭包。 + + // 我们改变选项列表的可见性 + toggleOptList(select); + }); + + // 如果组件获得了焦点 + // 每当用户点击它或是用tab键访问这个组件时,组件获得焦点 + select.addEventListener('focus', function (event) { + // 注意:'select'和'selectlist'变量是我们函数调用范围内有效的闭包 。 + + // 我们激活这个组件 + activeSelect(select, selectList); + }); + + // 如果组件失去焦点 + select.addEventListener('blur', function (event) { + // 注意:'select'变量是我们函数调用范围内有效的闭包。 + + // 我们关闭这个组件 + deactivateSelect(select); + }); + }); +});</pre> + +<p>此时,我们的组件会根据我们的设计改变状态,但是它的值仍然没有更新。我们接下来会处理这件事。</p> + +<table> + <thead> + <tr> + <th scope="col" style="text-align: center;">Live example</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{EmbedLiveSample("Change_states",120,130, "", "/Learn/HTML/Forms/How_to_build_custom_form_widgets/Example_3")}}</td> + </tr> + <tr> + <td style="text-align: center;"><a href="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets/Example_3" title="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets/Example_3">Check out the source code</a></td> + </tr> + </tbody> +</table> + +<h3 id="处理组件的值">处理组件的值</h3> + +<p>既然我们的组件已经开始工作了,我们必须添加代码,使其能够根据用户的输入更新取值,并且能将取值随表单数据一同发送。</p> + +<p>实现这一点最简单的方法是使用后台原生组件。这样的一个组件会使用浏览器提供的所有内置控件跟踪值,并且在表单提交时,取值也会像往常一样发送。当有现成的功能时,我们再做重复工作就毫无意义了。</p> + +<p>像前面所看到的那样,出于可访问性的原因,我们已经使用了一个原生的选择组件作为后备显示内容;我们可轻松的将它的值与我们的自定义组件之间的值同步。</p> + +<pre class="brush: js">// 这个函数更新显示的值并将其通过原生组件同步 +// 它需要2个参数: +// select : 含有要更新的值的'select'类的DOM节点 +// index : 要被选择的值的索引 +function updateValue(select, index) { + // 我们需要为了给定的自定义组件获取原生组件 + // 在我们的例子中, 原生组件是自定义组件的‘同胞’ + var nativeWidget = select.previousElementSibling; + + // 我们也需要得到自定义组件的值占位符, + var value = select.querySelector('.value'); + + // 还有整个选项列表。 + var optionList = select.querySelectorAll('.option'); + + // 我们将被选择的索引设定为我们的选择的索引 + nativeWidget.selectedIndex = index; + + // 更新相应的值占位符 + value.innerHTML = optionList[index].innerHTML; + + // 然后高亮我们自定义组件里对应的选项 + highlightOption(select, optionList[index]); +}; + +// 这个函数返回原生组件里当前选定的索引 +// 它需要1个参数: +// select : 跟原生组件有关的'select'类DOM节点 +function getIndex(select) { + // 我们需要为了给定的自定义组件访问原生组件 + // 在我们的例子中, 原生组件是自定义组件的一个“同胞” + var nativeWidget = select.previousElementSibling; + + return nativeWidget.selectedIndex; +};</pre> + +<p>通过这两个函数,我们可以将原生组件绑定到自定义的组件上。</p> + +<pre class="brush: js">// 我们在文档加载时处理事件的绑定。 +window.addEventListener('load', function () { + var selectList = document.querySelectorAll('.select'); + + // 每个自定义组件都需要初始化 + selectList.forEach(function (select) { + var optionList = select.querySelectorAll('.option'), + selectedIndex = getIndex(select); + + // 使我们的自定义组件可以获得焦点 + select.tabIndex = 0; + + // 我们让原生组件无法获得焦点 + select.previousElementSibling.tabIndex = -1; + + // 确保默认选中的值正确显示 + updateValue(select, selectedIndex); + + // 每当用户点击一个选项的时候,更新相应的值 + optionList.forEach(function (option, index) { + option.addEventListener('click', function (event) { + updateValue(select, index); + }); + }); + + // 每当用户在获得焦点的组件上用键盘操作时,更新相应的值 + select.addEventListener('keyup', function (event) { + var length = optionList.length, + index = getIndex(select); + + // 当用户点击向下箭头时,跳转到下一个选项 + if (event.keyCode === 40 && index < length - 1) { index++; } + + // 当用户点击向上箭头时,跳转到上一个选项 + if (event.keyCode === 38 && index > 0) { index--; } + + updateValue(select, index); + }); + }); +});</pre> + +<p>在上面的代码里,值得注意的是 <code><a href="/en-US/docs/Web/API/HTMLElement/tabIndex" title="/en-US/docs/Web/API/HTMLElement/tabIndex">tabIndex</a></code> 属性的使用。使用这个属性是很有必要的,这可以确保原生组件将永远不会获得焦点,而且还可以确保当用户用户使用键盘和鼠标时,我们的自定义组件能够获得焦点。</p> + +<p>做完上面这些后,我们就完成了!下面是结果:</p> + +<table> + <thead> + <tr> + <th scope="col" style="text-align: center;">Live example</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{EmbedLiveSample("Change_states",120,130, "", "/Learn/HTML/Forms/How_to_build_custom_form_widgets/Example_4")}}</td> + </tr> + <tr> + <td style="text-align: center;"><a href="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets/Example_4" title="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets/Example_4">Check out the source code</a></td> + </tr> + </tbody> +</table> + +<p>但是等等,我们真的做完了嘛?</p> + +<h2 id="使其具有可访问性">使其具有可访问性</h2> + +<p>我们构建了一个能够生效的东西,尽管这离一个特性齐全的选择框还差得远,但是它效果不错。但是我们已经完成的事情只不过是摆弄DOM。这个组件并没有真正的语义,即使它看起来像一个选择框,但是从浏览器的角度来看并不是,所以辅助技术并不能明白这是一个选择框。简单来说,这个全新的选择框并不具备可访问性!</p> + +<p>幸运的是,有一种解决方案叫做 <a href="/en-US/docs/Accessibility/ARIA" title="/en-US/docs/Accessibility/ARIA">ARIA</a>。ARIA代表"无障碍富互联网应用"。这是一个专为我们现在做的事情设计的<a href="http://www.w3.org/TR/wai-aria/" rel="external" title="http://www.w3.org/TR/wai-aria/"> W3C 规范</a>:使网络应用和自定义组件易于访问,它本质上是一组用来拓展 HTML 的属性集,以便我们能够更好的描述角色,状态和属性,就像我们刚才设计的元素是是它试图传递的原生元素一样。使用这些属性非常简单,所以让我们来试试看。</p> + +<h3 id="role_属性"> <code>role</code> 属性</h3> + +<p><a href="/en-US/docs/Accessibility/ARIA" title="/en-US/docs/Accessibility/ARIA">ARIA</a> 使用的关键属性是 <a href="/en-US/docs/Accessibility/ARIA/ARIA_Techniques" title="/en-US/docs/Accessibility/ARIA/ARIA_Techniques"><code>role</code></a> 属性。<a href="/en-US/docs/Accessibility/ARIA/ARIA_Techniques" title="/en-US/docs/Accessibility/ARIA/ARIA_Techniques"><code>role</code></a> 属性接受一个值,该值定义了一个元素的用途。每一个 role 定义了它自己的需求和行为。在我们的例子中,我们会使用 <code><a href="/en-US/docs/Accessibility/ARIA/ARIA_Techniques/Using_the_listbox_role" title="/en-US/docs/Accessibility/ARIA/ARIA_Techniques/Using_the_listbox_role">listbox</a></code> 这一 role。这是一个 "合成角色",表示具有该role的元素应该有子元素,每个子元素都有特定的角色。(在这个案例中,至少有一个具有<code>option</code> 角色的子元素)。</p> + +<p>同样值得注意的是,ARIA定义了默认应用于标准 HTML 标记的角色。例如,{{HTMLElement("table")}} 元素与角色 <code>grid</code> 相匹配,而 {{HTMLElement("ul")}} 元素与角色 <code>list</code> 相匹配。由于我们使用了一个 {{HTMLElement("ul")}} 元素,我们想要确保我们组件的 <code>listbox</code> 角色能替代 {{HTMLElement("ul")}} 元素的<code>list</code> 角色。为此,我们会使用角色 <code>presentation</code>。这个角色被设计成让我们来表示一个元素没有特殊的含义,并且仅仅用于提供信息。我们会将其应用到{{HTMLElement("ul")}} 元素上。</p> + +<p>为了支持 <code><a href="/en-US/docs/Accessibility/ARIA/ARIA_Techniques/Using_the_listbox_role" title="/en-US/docs/Accessibility/ARIA/ARIA_Techniques/Using_the_listbox_role">listbox</a></code> 角色,我们只需要将我们 HTML 改成这样:</p> + +<pre class="brush: html"><!-- 我们把role="listbox" 属性添加到我们的顶部元素 --> +<div class="select" role="listbox"> + <span class="value">Cherry</span> + <!-- 我们也把 role="presentation" 添加到ul元素中 --> + <ul class="optList" role="presentation"> + <!-- 然后把role="option" 属性添加到所有li元素里 --> + <li role="option" class="option">Cherry</li> + <li role="option" class="option">Lemon</li> + <li role="option" class="option">Banana</li> + <li role="option" class="option">Strawberry</li> + <li role="option" class="option">Apple</li> + </ul> +</div></pre> + +<div class="note"> +<p><strong>注意:</strong>只有当你想要为不支持 <a href="/en-US/docs/CSS/Attribute_selectors" title="/en-US/docs/CSS/Attribute_selectors">CSS 属性选择器的</a>旧浏览器提供支持时,才有必要同时包含 <code>role</code> 属性和一个<code>class</code> 属性。</p> +</div> + +<h3 id="aria-selected_属性"> <code>aria-selected</code> 属性</h3> + +<p>仅仅使用 <a href="/en-US/docs/Accessibility/ARIA/ARIA_Techniques" title="/en-US/docs/Accessibility/ARIA/ARIA_Techniques"><code>role</code></a> 属性是不够的。 <a href="/en-US/docs/Accessibility/ARIA" title="/en-US/docs/Accessibility/ARIA">ARIA</a> 还提供了许多状态和属性的内部特征。你能更好更充分的利用它们,你的组件就会能够被辅助技术更好的理解。在我们的例子中,我们会把使用限制在一个属性上:<code>aria-selected</code>。</p> + +<p><code>aria-selected</code> 属性被用来标记当前被选中的选项;这可以让辅助技术告知用户当前的选项是什么。我们会通过 JavaScript 动态地使用该属性,每当用户选择一个选项时标记选中的选项。为了达到这一目的,我们需要修正我们的 <code>updateValue()</code> 函数:</p> + +<pre class="brush: js">function updateValue(select, index) { + var nativeWidget = select.previousElementSibling; + var value = select.querySelector('.value'); + var optionList = select.querySelectorAll('.option'); + + // 我们确保所有的选项都没有被选中 + optionList.forEach(function (other) { + other.setAttribute('aria-selected', 'false'); + }); + + // 我们确保选定的选项被选中了 + optionList[index].setAttribute('aria-selected', 'true'); + + nativeWidget.selectedIndex = index; + value.innerHTML = optionList[index].innerHTML; + highlightOption(select, optionList[index]); +};</pre> + +<p>这是经过所有的改变之后的最终结果。 ( 藉由 <a href="http://www.nvda-project.org/" rel="external" title="http://www.nvda-project.org/">NVDA</a> or <a href="http://www.apple.com/accessibility/voiceover/" rel="external" title="http://www.apple.com/accessibility/voiceover/">VoiceOver</a> 这样的辅助技术尝试它,你会对此有更好的体会):</p> + +<table> + <thead> + <tr> + <th scope="col" style="text-align: center;">在线示例</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{EmbedLiveSample("Change_states",120,130, "", "/Learn/HTML/Forms/How_to_build_custom_form_widgets/Example_5")}}</td> + </tr> + <tr> + <td style="text-align: center;"><a href="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets/Example_5" title="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets/Example_5">Check out the final source code</a></td> + </tr> + </tbody> +</table> + +<h2 id="总结">总结</h2> + +<p>我们已经了解了所有和构建一个自定义表单组件相关的基础知识,但是如你所见做这件事非常繁琐,并且通常情况下依赖第三方库,而不是自己从头写起会更容易 ,也更好(当然,除非你的目的就是构建一个这样的库)。</p> + +<p>这儿有一些库,在你编写自己的之前应该了解一下:</p> + +<ul> + <li><a href="http://jqueryui.com/" rel="external" title="http://jqueryui.com/">jQuery UI</a></li> + <li><a href="https://github.com/marghoobsuleman/ms-Dropdown" rel="external" title="https://github.com/marghoobsuleman/ms-Dropdown">msDropDown</a></li> + <li><a href="http://www.emblematiq.com/lab/niceforms/" rel="external" title="http://www.emblematiq.com/lab/niceforms/">Nice Forms</a></li> + <li><a href="https://www.google.fr/search?q=HTML+custom+form+controls&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:fr:official&client=firefox-a" rel="external" title="https://www.google.fr/search?q=HTML+custom+form+controls&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:fr:official&client=firefox-a">And many more…</a></li> +</ul> + +<p>如果你想更进一步, 本例中的代码需要一些改进,才能变得更加通用和可重用。这是一个你可以尝试去做的练习。这里有两个提示可以帮到你:我们所有函数的第一个参数是相同的,这意味着这些函数需要相同的上下文。构建一个对象来共享那些上下文是更聪明的做法。还有,你需要让它的特性适用性更好;也就是说,它要能在一系列对Web标准的兼容性不同的浏览器上工作良好。祝愉快!</p> + +<p>{{PreviousMenuNext("Learn/HTML/Forms/Form_validation", "Learn/HTML/Forms/Sending_forms_through_JavaScript", "Learn/HTML/Forms")}}</p> + +<h2 id="在本单元中">在本单元中</h2> + +<ul> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Your_first_HTML_form">Your first HTML form</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/How_to_structure_an_HTML_form">How to structure an HTML form</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/The_native_form_widgets">The native form widgets</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Sending_and_retrieving_form_data">Sending form data</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Form_validation">Form data validation</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/How_to_build_custom_form_widgets">How to build custom form widgets</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Sending_forms_through_JavaScript">Sending forms through JavaScript</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/HTML_forms_in_legacy_browsers">HTML forms in legacy browsers</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Styling_HTML_forms">Styling HTML forms</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Advanced_styling_for_HTML_forms">Advanced styling for HTML forms</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Property_compatibility_table_for_form_widgets">Property compatibility table for form widgets</a></li> +</ul> diff --git a/files/zh-cn/learn/html/forms/how_to_structure_an_html_form/index.html b/files/zh-cn/learn/html/forms/how_to_structure_an_html_form/index.html new file mode 100644 index 0000000000..eda4b201da --- /dev/null +++ b/files/zh-cn/learn/html/forms/how_to_structure_an_html_form/index.html @@ -0,0 +1,290 @@ +--- +title: 如何构造HTML表单 +slug: Learn/HTML/Forms/How_to_structure_an_HTML_form +translation_of: Learn/Forms/How_to_structure_a_web_form +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/HTML/Forms/Your_first_HTML_form", "Learn/HTML/Forms/The_native_form_widgets", "Learn/HTML/Forms")}}</div> + +<p class="summary">有了基础知识,我们现在更详细地了解了用于为表单的不同部分提供结构和意义的元素。</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">前提条件:</th> + <td>基本的计算机能力, 和基本的 <a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Introduction_to_HTML">对HTML的理解</a>。</td> + </tr> + <tr> + <th scope="row">目标:</th> + <td>要理解如何构造HTML表单并赋予它们语义,以便它们是可用的和可访问的。</td> + </tr> + </tbody> +</table> + +<p>HTML表单的灵活性使它们成为HTML中最复杂的结构之一;您可以使用专用的表单元素和属性构建任何类型的基本表单。在构建HTML表单时使用正确的结构将有助于确保表单可用性和可访问性。</p> + +<h2 id="<form>_元素"> <form> 元素</h2> + +<p> {{HTMLElement("form")}} 元素按照一定的格式定义了表单和确定表单行为的属性。当您想要创建一个HTML表单时,都必须从这个元素开始,然后把所有内容都放在里面。许多辅助技术或浏览器插件可以发现{{HTMLElement("form")}}元素并实现特殊的钩子,使它们更易于使用。 </p> + +<p>我们早在之前的文章中就遇见过它了。</p> + +<div class="note"><strong>注意:</strong> 严格禁止在一个表单内嵌套另一个表单。嵌套会使表单的行为不可预知,而这取决于正在使用的浏览器。</div> + +<p>请注意,在{{HTMLElement("form")}}元素之外使用表单小部件是可以的,但是如果您这样做了,那么表单小部件与任何表单都没有任何关系。这样的小部件可以在表单之外使用,但是您应该对于这些小部件有特别的计划,因为它们自己什么也不做。您将不得不使用JavaScript定制他们的行为。</p> + +<div class="note"> +<p><strong>注意</strong>: HTML5在HTML表单元素中引入<code>form</code>属性。它让您显式地将元素与表单绑定在一起,即使元素不在{{ HTMLElement("form") }}中。不幸的是,就目前而言,跨浏览器对这个特性的实现还不足以使用。</p> +</div> + +<h2 id="<fieldset>_和_<legend>_元素"> <fieldset> 和 <legend> 元素</h2> + +<p>{{HTMLElement("fieldset")}}元素是一种方便的用于创建具有相同目的的小部件组的方式,出于样式和语义目的。 你可以在<code><fieldset></code>开口标签后加上一个 {{HTMLElement("legend")}}元素来给{{HTMLElement("fieldset")}} 标上标签。 {{HTMLElement("legend")}}的文本内容正式地描述了{{HTMLElement("fieldset")}}里所含有部件的用途。</p> + +<p>许多辅助技术将使用{{HTMLElement("legend")}} 元素,就好像它是相应的 {{HTMLElement("fieldset")}} 元素里每个部件的标签的一部分。例如,在说出每个小部件的标签之前,像<a href="http://www.freedomscientific.com/products/fs/jaws-product-page.asp" rel="external" title="http://www.freedomscientific.com/products/fs/jaws-product-page.asp">Jaws</a>或<a href="http://www.nvda-project.org/" rel="external" title="http://www.nvda-project.org/">NVDA</a>这样的屏幕阅读器会朗读出legend的内容。</p> + +<p>这里有一个小例子:</p> + +<pre class="brush:html;"><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></pre> + +<div class="note"> +<p><strong>注意</strong>: 你可以在 <a href="https://github.com/mdn/learning-area/blob/master/html/forms/html-form-structure/fieldset-legend.html">fieldset-legend.html</a> (你也可以看<a href="https://mdn.github.io/learning-area/html/forms/html-form-structure/fieldset-legend.html">预览版</a>) 看到该例。</p> +</div> + +<p>当阅读上述表格时,屏幕阅读器将会读第一个小部件“Fruit juice size small”,“Fruit juice size medium”为第二个,“Fruit juice size large”为第三个。</p> + +<p>本例中的用例是最重要的。每当您有一组单选按钮时,您应该将它们嵌套在{{HTMLElement("fieldset")}}元素中。还有其他用例,一般来说,{{HTMLElement("fieldset")}}元素也可以用来对表单进行分段。理想情况下,长表单应该在拆分为多个页面,但是如果表单很长,却必须在单个页面上,那么将以不同的关联关系划分的分段,分别放在不同的fieldset里,可以提高可用性。</p> + +<p>因为它对辅助技术的影响, {{HTMLElement("fieldset")}} 元素是构建可访问表单的关键元素之一。无论如何,你有责任不去滥用它。如果可能,每次构建表单时,尝试侦听<a href="https://www.nvaccess.org/download/" title="屏幕阅读器">屏幕阅读器</a>如何解释它。如果听起来很奇怪,试着改进表单结构。</p> + +<h2 id="<label>_元素"> <label> 元素</h2> + +<p>正如我们在前一篇文章中看到的, {{HTMLElement("label")}} 元素是为HTML表单小部件定义标签的正式方法。如果你想构建可访问的表单,这是最重要的元素——当实现的恰当时,屏幕阅读器会连同有关的说明和表单元素的标签一起朗读。以我们在上一篇文章中看到的例子为例:</p> + +<pre class="brush: html"><label for="name">Name:</label> <input type="text" id="name" name="user_name"></pre> + +<p><code><label></code> 标签与 <code><input></code> 通过他们各自的<code>for</code> 属性和 <code>id</code> 属性正确相关联(label的for属性和它对应的小部件的id属性),这样,屏幕阅读器会读出诸如“Name, edit text”之类的东西。</p> + +<p>如果标签没有正确设置,屏幕阅读器只会读出“Edit text blank”之类的东西,这样会没什么帮助。</p> + +<p>注意,一个小部件可以嵌套在它的{{HTMLElement("label")}}元素中,就像这样:</p> + +<pre class="brush: html"><label for="name"> + Name: <input type="text" id="name" name="user_name"> +</label></pre> + +<p>尽管可以这样做,但人们认为设置<code>for</code>属性才是最好的做法,因为一些辅助技术不理解标签和小部件之间的隐式关系。</p> + +<h3 id="标签也可点击!">标签也可点击!</h3> + +<p>正确设置标签的另一个好处是可以在所有浏览器中单击标签来激活相应的小部件。这对于像文本输入这样的例子很有用,这样你可以通过点击标签,和点击输入区效果一样,来聚焦于它,这对于单选按钮和复选框尤其有用——这种控件的可点击区域可能非常小,设置标签来使它们可点击区域变大是非常有用的。</p> + +<p>举个例子:</p> + +<pre class="brush:html;"><form> + <p> + <label for="taste_1">I like cherry</label> + <input type="checkbox" id="taste_1" name="taste_cherry" value="1"> + </p> + <p> + <label for="taste_2">I like banana</label> + <input type="checkbox" id="taste_2" name="taste_banana" value="2"> + </p> +</form></pre> + +<div class="note"> +<p><strong>注意</strong>: 你可以在 <a href="https://github.com/mdn/learning-area/blob/master/html/forms/html-form-structure/checkbox-label.html">checkbox-label.html</a> (你也可以看<a href="https://mdn.github.io/learning-area/html/forms/html-form-structure/checkbox-label.html">预览版</a>) 看到该例。</p> +</div> + +<h3 id="多个标签">多个标签</h3> + +<p>严格地说,您可以在一个小部件上放置多个标签,但是这不是一个好主意,因为一些辅助技术可能难以处理它们。在多个标签的情况下,您应该将一个小部件和它的标签嵌套在一个{{HTMLElement("label")}}元素中。</p> + +<p>让我们考虑下面这个例子:</p> + +<pre class="brush: html"><p>Required fields are followed by <abbr title="required">*</abbr>.</p> + +<!--这样写:--> +<div> + <label for="username">Name:</label> + <input type="text" name="username"> + <label for="username"><abbr title="required">*</abbr></label> +</div> + +<!--但是这样写会更好:--> +<div> + <label for="username"> + <span>Name:</span> + <input id="username" type="text" name="username"> + <abbr title="required">*</abbr> + </label> +</div> + +<!--但最好的可能是这样:--> +<div> + <label for="username">Name: <abbr title="required">*</abbr></label> + <input id="username" type="text" name="username"> +</div></pre> + +<p>顶部的段落定义了所需元素的规则。它必须在开始时确保像屏幕阅读器这样的辅助技术在用户找到必需的元素之前显示或念出它们。这样,他们就知道星号表达的是什么意思了。根据屏幕阅读器的设置,屏幕阅读器会把星号读为“star”或“required”,取决于屏幕阅读器的设置——不管怎样,要念出来的都会在第一段清楚的呈现出来。</p> + +<ul> + <li>在第一个例子中,标签根本没有和<code>input</code>一起被念出来——读出来的只是“edit the blank”,和单独被念出的标签。多个<code><label></code>元素会使屏幕阅读器迷惑。</li> + <li>在第二个例子中,事情变得清晰一点了——标签和输入一起,读出的是“name star name edit text”,但标签仍然是单独读出的。这还是有点令人困惑,但这次还是稍微好一点了,因为<code>input</code>和<code>label</code>联系起来了。</li> + <li>第三个例子是最好的——标签是一起读出的,标签和输入读出的是“name star edit text”。</li> +</ul> + +<div class="note"> +<p><strong>注意</strong>:你可能会得到一些不同的结果,这取决于你的屏幕阅读器。这是在VoiceOver上测试的(NVDA的行为也类似)。我们也乐于听听你的试验结果。</p> +</div> + +<div class="note"> +<p><strong>注意</strong>: 你可以在 GitHub 上看到 <a href="https://github.com/mdn/learning-area/blob/master/html/forms/html-form-structure/required-labels.html">required-labels.html</a> (你也可以看<a href="https://mdn.github.io/learning-area/html/forms/html-form-structure/required-labels.html">预览版</a>)。不要运行2个或3个未注释版本的示例—— 如果您有多个标签和多个输入相同的ID,那么屏幕阅读器肯定会感到困惑!</p> +</div> + +<h2 id="用于表单的通用HTML结构">用于表单的通用HTML结构</h2> + +<p>除了特定于HTML表单的结构之外,还应该记住表单同样是HTML。这意味着您可以使用HTML的所有强大功能来构造一个HTML表单。</p> + +<p>正如您在示例中可以看到的,用{{HTMLElement("div")}}元素包装标签和它的小部件是很常见的做法。{{HTMLElement("p")}}元素也经常被使用,HTML列表也是如此(后者在构造多个复选框或单选按钮时最为常见)。</p> + +<p>除了{{HTMLElement("fieldset")}}元素之外,使用HTML标题(例如,{{htmlelement("h1")}}、{{htmlelement("h2")}})和分段(如{{htmlelement("section")}})来构造一个复杂的表单也是一种常见的做法。</p> + +<p>最重要的是,你要找到一种你觉得很舒服的风格去码代码,而且它也能带来可访问的、可用的形式。</p> + +<p>它包含了从功能上划分开并分别包含在{{htmlelement("section")}}元素中的部分,以及一个{{htmlelement("fieldset")}}来包含单选按钮。</p> + +<h3 id="自主学习构建一个表单结构">自主学习:构建一个表单结构</h3> + +<p>让我们把这些想法付诸实践,建立一个稍微复杂一点的表单结构——一个支付表单。这个表单将包含许多您可能还不了解的小部件类型—现在不要担心这个;在下一篇文章(<a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/The_native_form_widgets">原生表单小部件</a>)中,您将了解它们是如何工作的。现在,当您遵循下面的指令时,请仔细阅读这些描述,并开始理解我们使用的包装器元素是如何构造表单的,以及为什么这么做。</p> + +<ol> + <li>在开始之前,在计算机上的一个新目录中,创建一个<a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/getting-started/index.html">空白模板文件</a>和<a href="https://github.com/mdn/learning-area/blob/master/html/forms/html-form-structure/payment-form.css">我们的支付表单的CSS样式</a>的本地副本。</li> + <li>首先,通过添加下面这行代码到你的HTML{{htmlelement("head")}}使你的HTML应用CSS。 + <pre class="brush: html"><link href="payment-form.css" rel="stylesheet"></pre> + </li> + <li>接下来,通过添加外部{{htmlelement("form")}}元素来开始一张表单: + <pre class="brush: html"><form> + +</form></pre> + </li> + <li>在 <code><form></code> 标签内,以添加一个标题和段落开始,告诉用户必需的字段是如何标记的: + <pre class="brush: html"><h1>Payment form</h1> +<p>Required fields are followed by <strong><abbr title="required">*</abbr></strong>.</p></pre> + </li> + <li>接下来,我们将在表单中添加一个更大的代码段,在我们之前的代码下面。在这里,您将看到,我们正在将联系人信息字段包装在一个单独的{{htmlelement("section")}}元素中。此外,我们有一组两个单选按钮,每个单选按钮都放在自己的列表中({{htmlelement("li")}}))元素。最后,我们有两个标准文本{{htmlelement("input")}}和它们相关的{{htmlelement("label")}}元素,每个元素包含在{{htmlelement("p")}}中,加上输入密码的密码输入。现在将这些代码添加到您的表单中: + <pre><section> + <h2>Contact information</h2> + <fieldset> + <legend>Title</legend> + <ul> + <li> + <label for="title_1"> + <input type="radio" id="title_1" name="title" value="K" > + King + </label> + </li> + <li> + <label for="title_2"> + <input type="radio" id="title_2" name="title" value="Q"> + Queen + </label> + </li> + <li> + <label for="title_3"> + <input type="radio" id="title_3" name="title" value="J"> + Joker + </label> + </li> + </ul> + </fieldset> + <p> + <label for="name"> + <span>Name: </span> + <strong><abbr title="required">*</abbr></strong> + </label> + <input type="text" id="name" name="username"> + </p> + <p> + <label for="mail"> + <span>E-mail: </span> + <strong><abbr title="required">*</abbr></strong> + </label> + <input type="email" id="mail" name="usermail"> + </p> + <p> + <label for="pwd"> + <span>Password: </span> + <strong><abbr title="required">*</abbr></strong> + </label> + <input type="password" id="pwd" name="password"> + </p> +</section></pre> + </li> + <li>现在,我们将转到表单的第二个<code><section></code>——支付信息。在这里,我们有三个不同的小部件以及它们的标签,每个都包含在一个<code><p></code>中。第一个是选择信用卡类型的下拉菜单({{htmlelement("select")}})。第二个是输入一个信用卡号的类型编号的 <code><input></code> 元素。最后一个是输入<code>date</code>类型的<code><input></code> 元素,用来输入卡片的过期日期(这将在支持的浏览器中出现一个日期选择器小部件,并在非支持的浏览器中回退到普通的文本输入)。同样,在之前的代码后面输入以下内容: + <pre class="brush: html"><section> + <h2>Payment information</h2> + <p> + <label for="card"> + <span>Card type:</span> + </label> + <select id="card" name="usercard"> + <option value="visa">Visa</option> + <option value="mc">Mastercard</option> + <option value="amex">American Express</option> + </select> + </p> + <p> + <label for="number"> + <span>Card number:</span> + <strong><abbr title="required">*</abbr></strong> + </label> + <input type="number" id="number" name="cardnumber"> + </p> + <p> + <label for="date"> + <span>Expiration date:</span> + <strong><abbr title="required">*</abbr></strong> + <em>formatted as mm/yy</em> + </label> + <input type="date" id="date" name="expiration"> + </p> +</section></pre> + </li> + <li>我们要添加的最后一个部分要简单得多,它只包含了一个<code>submit</code>类型的 {{htmlelement("button")}} ,用于提交表单数据。现在把这个添加到你的表单的底部: + <pre class="brush: html"><p> <button type="submit">Validate the payment</button> </p></pre> + </li> +</ol> + +<p>您可以在下面看到已完成的表单 (你可以在Github上看到<a href="https://github.com/mdn/learning-area/blob/master/html/forms/html-form-structure/payment-form.html">源码</a>和<a href="https://mdn.github.io/learning-area/html/forms/html-form-structure/payment-form.html">预览版</a>):</p> + +<p>{{EmbedLiveSample("A_payment_form","100%",620, "", "Learn/HTML/Forms/How_to_structure_an_HTML_form/Example")}}</p> + +<h2 id="总结">总结</h2> + +<p>现在,您已经具备了正确地构造HTML表单所需的所有知识;下一篇文章将深入介绍各种不同类型的表单小部件,您将希望从用户那里收集信息。</p> + +<h2 id="另见">另见</h2> + +<ul> + <li><a href="http://www.alistapart.com/articles/sensibleforms/" rel="external" title="http://www.alistapart.com/articles/sensibleforms/">A List Apart: <em>Sensible Forms: A Form Usability Checklist</em></a></li> +</ul> + +<p>{{PreviousMenuNext("Learn/HTML/Forms/Your_first_HTML_form", "Learn/HTML/Forms/The_native_form_widgets", "Learn/HTML/Forms")}}</p> diff --git a/files/zh-cn/learn/html/forms/html_forms_in_legacy_browsers/index.html b/files/zh-cn/learn/html/forms/html_forms_in_legacy_browsers/index.html new file mode 100644 index 0000000000..d6045e0d70 --- /dev/null +++ b/files/zh-cn/learn/html/forms/html_forms_in_legacy_browsers/index.html @@ -0,0 +1,215 @@ +--- +title: 旧式浏览器中的HTML 表单 +slug: Learn/HTML/Forms/HTML_forms_in_legacy_browsers +translation_of: Learn/Forms/HTML_forms_in_legacy_browsers +--- +<div>{{LearnSidebar}}{{PreviousMenuNext("Learn/HTML/Forms/Sending_forms_through_JavaScript", "Learn/HTML/Forms/Styling_HTML_forms", "Learn/HTML/Forms")}}</div> + +<p class="summary">所有 web 开发者很快就会(有时候是痛苦地)发现网络是一个令人不快的地方。我们碰到的最恶毒的诅咒是旧式浏览器。好吧,让我们承认吧,当我们提到 “旧式浏览器” 时,脑海中出现就是 老版本的 Internet Explorer ……但是,这远远不是全部。只发布一年的 Firefox 比如 <a href="http://www.mozilla.org/en-US/firefox/organizations/" title="http://www.mozilla.org/en-US/firefox/organizations/">the ESR version</a> 也是旧式浏览器。那么,在移动世界呢?当浏览器和 OS(操作系统) 都不能更新时?是的,有非常多老版本的 Android 手机或 iPhone 没有更新到最新的浏览器。它们同样是旧式浏览器。</p> + +<p>可悲的是,处理这些传统浏览器的问题是工作的一部分。幸运的是,有一些技巧可以帮助您解决旧式浏览器导致的大约80%的问题。</p> + +<h2 id="了解这些问题">了解这些问题</h2> + +<p>实际上,最重要的事情是阅读那些浏览器的文档,并尝试理解通用的(解决)模式。例如,在许多情况下,HTML表单是否支持CSS是最大的问题。这是正确的开始,只需要检查你想用的元素或接口是否支持CSS即可。MDN有一个关于包含HTML中可用的元素、属性或API的兼容表单可查。 此外,仍有其他一些非常有用的资源:</p> + +<h3 id="浏览器厂商的文档">浏览器厂商的文档</h3> + +<ul> + <li>Mozilla: 直接查看MDN即可</li> + <li>Microsoft: <a href="http://msdn.microsoft.com/en-us/library/ff410218%28v=vs.85%29.aspx" rel="external" title="http://msdn.microsoft.com/en-us/library/ff410218%28v=vs.85%29.aspx">Internet Explorer Standards Support Documentation</a></li> + <li>WebKit: 由于有多个版本的引擎,稍微有点棘手. + <ul> + <li><a href="https://www.webkit.org/blog/" rel="external" title="https://www.webkit.org/blog/">The WebKit blog</a> 和 <a href="http://planet.webkit.org/" rel="external" title="http://planet.webkit.org/">Planet WebKit</a> 聚合了Webki核心开发者的最佳文章.</li> + <li><a href="https://www.chromestatus.com/features" title="http://www.chromium.org/developers/web-platform-status">Chrome platform status site</a> 也十分重要</li> + <li>同样重要的是 <a href="https://developer.apple.com/technologies/safari/" rel="external" title="https://developer.apple.com/technologies/safari/">the Apple web site.</a></li> + </ul> + </li> +</ul> + +<h3 id="独立文档">独立文档</h3> + +<ul> + <li><a href="http://caniuse.com" rel="external" title="http://caniuse.com">Can I Use</a> 有关于是否支持最新技术的信息.</li> + <li><a href="http://www.quirksmode.org" rel="external" title="http://www.quirksmode.org">Quirks Mode</a> 是关于浏览器兼容性的精彩资源. <a href="http://www.quirksmode.org/mobile/" rel="external" title="http://www.quirksmode.org/mobile/">mobile部分</a>是当前最好的内容之一.</li> + <li><a href="http://positioniseverything.net/" rel="external" title="http://positioniseverything.net/">Position Is Everything</a> 关于旧式浏览器渲染bug以及解决办法(如果有)的最佳资源.</li> + <li><a href="http://mobilehtml5.org" rel="external" title="http://mobilehtml5.org">Mobile HTML5</a> 有关于大量手机浏览器的兼容性信息,而不仅仅是是前五名(包括诺基亚,亚马逊和黑莓).</li> +</ul> + +<h2 id="让事情变得更简单">让事情变得更简单</h2> + +<p>由于<a href="/en-US/docs/HTML/Forms" title="/en-US/docs/HTML/Forms">HTML forms</a> 包含复杂的交互,所以有一条法则: <a href="http://en.wikipedia.org/wiki/KISS_principle" rel="external" title="http://en.wikipedia.org/wiki/KISS_principle">keep it as simple as possible</a>。很多时候,我们想让表单更美观或想使用更高级的技术,然而,构建高效的HTML表单不只是设计和技术问题。记得花时间读一下这篇文章t <a href="http://www.uxforthemasses.com/forms-usability/" rel="external" title="http://www.uxforthemasses.com/forms-usability/">forms usability on UX For The Masses</a>.</p> + +<h3 id="优雅地降级(Graceful_degradation)是web开发者最好的朋友">优雅地降级(Graceful degradation)是web开发者最好的朋友</h3> + +<p><a href="http://www.sitepoint.com/progressive-enhancement-graceful-degradation-choice/" rel="external" title="http://www.sitepoint.com/progressive-enhancement-graceful-degradation-choice/">Graceful degradation and progressive enhancement</a> 是一个开发模式,它允许你通过同时支持多种浏览器来构建优秀内容。当你为现代浏览器构建内容时,你想确保它能在旧式浏览器中以某种方式工作,这就是优雅地降级(graceful degradation).</p> + +<p>让我们看一些关于HTML表单的例子:</p> + +<h4 id="HTML_input_类型">HTML input 类型</h4> + +<p>HTML5引入的新input类型十分酷,因为他们的降级(degrade)是高度可预测的。如果一个浏览器不能理解 {{HTMLElement("input")}}元素的 {{htmlattrxref("type","input")}} 属性, 它将会后退到<code>text</code>一样的行为。</p> + +<pre class="brush: html"><label for="myColor"> + Pick a color + <input type="color" id="myColor" name="color"> +</label></pre> + +<table> + <thead> + <tr> + <th scope="col" style="text-align: center;">Chrome 24</th> + <th scope="col" style="text-align: center;">Firefox 18</th> + </tr> + </thead> + <tbody> + <tr> + <th style="text-align: center;"><img alt="Screen shot of the color input on Chrome for Mac OSX" src="/files/4575/color-fallback-chrome.png" style="height: 35px; width: 139px;"></th> + <th style="text-align: center;"><img alt="Screen shot of the color input on Firefox for Mac OSX" src="/files/4577/color-fallback-firefox.png" style="height: 30px; width: 245px;"></th> + </tr> + </tbody> +</table> + +<h4 id="CSS_属性选择器">CSS 属性选择器</h4> + +<p><a href="/en-US/docs/CSS/Attribute_selectors" title="/en-US/docs/CSS/Attribute_selectors">CSS属性选择器 </a> 在 <a href="/en-US/docs/HTML/Forms" title="/en-US/docs/HTML/Forms">HTML Forms</a> 中十分有用,然而旧式浏览器不支持. 在那种情形下,一般会习惯性使用等价的class:</p> + +<pre class="brush: html"><input type="number" class="number"></pre> + +<pre class="brush: css">input[type=number] { + /* 这在一些浏览器中是不能执行的 */ +} + +input.number { + /* 可以在任何浏览器中执行 */ +}</pre> + +<p>注意下面的写法没有用(由于它是重复的),在某些浏览器中会失败:</p> + +<pre class="brush: css">input[type=number], +input.number { + /* 在某些浏览器中,这可能会失败,因为如果他们不理解其中任何一个选择器,则跳过整个规则 */ +}</pre> + +<h4 id="表单按钮">表单按钮</h4> + +<p>有两种定义HTML表单按钮的方式:</p> + +<ul> + <li>{{HTMLElement("input")}} 元素使用{{htmlattrxref("type","input")}} 属性并设置其值为<code>button</code>, <code>submit</code>, <code>reset</code> or <code>image</code></li> + <li>{{HTMLElement("button")}} 元素</li> +</ul> + +<p>如果你想通过元素选择器在按钮上应用CSS的话,采用 {{HTMLElement("input")}} 元素的方式会让事情变得稍微有点复杂:</p> + +<pre class="brush: html"><input type="button" class="button" value="click me"></pre> + +<pre class="brush: css">input { + /* 此规则关闭了input元素定义的按钮的默认渲染样式 */ + border: 1px solid #CCC; +} + +input.button { + /* 这条规则不会恢复默认渲染*/ + border: none; +} + +input.button { + /* 这条也不会(恢复)! 实际上在浏览器中没有标准方式实现这一目标 */ + border: auto; +}</pre> + +<p>{{HTMLElement("button")}} 元素有两个问题令人困扰:</p> + +<ul> + <li>在某些旧版本的IE浏览器中有bug。当用户点击按钮时,它不是发送{{htmlattrxref("value","button")}}属性中的内容,而是发送 {{HTMLElement("button")}} 的开闭标签之间的HTML内容. 如果我们想发送值时,这是一个问题,例如发送的处理数据依赖于用户点击不同的按钮时.</li> + <li>一些旧浏览器不使用<code>submit</code> 作为 {{htmlattrxref("type","button")}} 属性的默认值, 所以建议总是在{{HTMLElement("button")}} 元素上设置设置 {{htmlattrxref("type","button")}} 属性.</li> +</ul> + +<pre class="brush: html"><!-- 某些情形下,点击按钮将发送 "<em>Do A</em>" 而不是值"A" --> +<button type="submit" name="IWantTo" value="A"> + <em>Do A</em> +</button></pre> + +<p>给予你的工程限制来选择上述任一种解决方案。</p> + +<h3 id="让我们过一遍CSS">让我们过一遍CSS</h3> + +<p>HTML表单和旧式浏览器最大的问题是CSS的兼容性。正如你可以从这篇文章 <a href="/en-US/docs/Property_compatibility_table_for_form_widgets" title="/en-US/docs/Property_compatibility_table_for_form_widgets">Property compatibility table for form widgets</a> 中看到的复杂性, 它非常的困难。即使仍然可以对文本元素(如大小、字体颜色等)进行一些调整,但那样做会有副作用。最好的办法还是不要美化HTML表单小组件。但你仍然可以将样式应用到表单周围的项目上。如果你是一个专业人士,并且你的客户需要那么做,在这种情况下,你可以研究一些硬技能,如 <a href="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets" title="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets">rebuilding widgets with JavaScript</a>。但在那种情况下,最好还是毫不犹豫的<a href="http://www.smashingmagazine.com/2011/11/03/but-the-client-wants-ie-6-support/" rel="external" title="http://www.smashingmagazine.com/2011/11/03/but-the-client-wants-ie-6-support/">让客户收回这些愚蠢的决定</a>。</p> + +<h2 id="功能检测和模拟(polyfills)">功能检测和模拟(polyfills)</h2> + +<p>尽管JavaScript在现代浏览中是非常棒的技术,但在旧式浏览器中可能存在很多的问题。</p> + +<h3 id="Unobtrusive_JavaScript">Unobtrusive JavaScript</h3> + +<p>API的兼容性是最大的问题。由于这个原因,与"不引人注意的(unobtrusive)" JavaScript一起工作被认为是最佳实践(译者注:此处意思是说没有/忽略JS或JS出了问题也能工作)。这个开发模式定义了两个需求:</p> + +<ul> + <li>结构和行为之间的严格隔离</li> + <li>如果代码出错,内容和基本功能必须保持可访问和可用状态</li> +</ul> + +<p><a href="http://docs.webplatform.org/wiki/concepts/programming/the_principles_of_unobtrusive_javascript" rel="external" title="http://docs.webplatform.org/wiki/concepts/programming/the_principles_of_unobtrusive_javascript">The principles of unobtrusive JavaScript</a> (最早是由Peter-Paul Koch为 Dev.Opera.com 所撰写,现在已转移到 Docs.WebPlatform.org) 同样阐述了上述观点。</p> + +<h3 id="Modernizr_库">Modernizr 库</h3> + +<p>有很多情形,好的"polyfill"能通过提供缺少的API以提供帮助。一个 <a href="http://remysharp.com/2010/10/08/what-is-a-polyfill/" rel="external" title="http://remysharp.com/2010/10/08/what-is-a-polyfill/">polyfill</a> 是一些JavaScript(脚本) 用于填补旧式浏览器中的功能缺失。虽然它们可以用来改进对任何功能的支持,并且使用它们Nederland风险小于CSS和HTML,然而,JS仍然会在很多情况下不工作(网络问题,脚本冲突等)。但是对于JavaScript,如果你总是记住和unobetructive的Javascript一起工作,不适用polyfill也没什么大不了。</p> + +<p>最好的polyfill缺失API的方式是使用<a href="http://modernizr.com" rel="external" title="http://modernizr.com">Modernizr</a> 库以及它的子项目 <a href="http://yepnopejs.com" rel="external" title="http://yepnopejs.com">YepNope</a>. Modernizr 库允许您测试功能可用性,以便采取相应的行动。YepNope 是一个条件加载库。</p> + +<p>下面是一个例子:</p> + +<pre class="brush: js">Modernizr.load({ + // 这会测试您的浏览器是否支持HTML5表单验证API + test : Modernizr.formvalidation, + + // 如果浏览器不支持它,则会加载以下polyfill + nope : form-validation-API-polyfill.js, + + // 无论如何,你的核心App文件依赖于该API被加载 + both : app.js, + + // 一旦加载了这两个文件,就会调用该函数来初始化应用程序 + complete : function () { + app.init(); + } +});</pre> + +<p>Modernizr 团队按照惯例维护着<a href="https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills" rel="external" title="https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills">a list of great polyfills</a>。仅仅按需使用即可。</p> + +<div class="note"> +<p><strong>Note:</strong> Modernizr还有其他很棒的功能可以帮助您处理unobstructive的JavaScript和优雅的降级技术。请阅读 <a href="http://modernizr.com/docs/" rel="external" title="http://modernizr.com/docs/">Modernizr documentation</a>.</p> +</div> + +<h3 id="注意性能">注意性能</h3> + +<p>尽管像Modernizr这样的脚本对性能非常敏感,但加载200千字节的polyfill仍然会影响程序的性能。这对旧式浏览器来说尤其重要,这些浏览器有处理速度非常慢的JavaScript引擎,让polyfills的执行对于用户来说变得很痛苦。性能本身就是一个主题,但旧式浏览器对它非常敏感:基本上,它们速度慢,需要的poliyfill越多,它们需要处理的JavaScript越多。与现代浏览器相比,它们承受双重负担。使用旧版浏览器测试你的代码,了解它们的实际表现。有时,放弃某些功能会带来更好的用户体验,而不是在所有浏览器中具有完全相同的功能。作为最后提醒,总是优先考虑用户。</p> + +<h2 id="总结">总结</h2> + +<p>正如你所看到的,处理旧式浏览器不仅仅是表单问题。而是一整套技术;但是掌握所有这些技术超出了本文的范围。</p> + +<p>如果你阅读了<a href="/en-US/docs/HTML/Forms" title="/en-US/docs/HTML/Forms">HTML Forms guide</a>中的所有文章,你应该可以放心的使用表单了。如果你想探索新技术,请帮助<a href="/en-US/docs/Project:How_to_help" title="/en-US/docs/Project:How_to_help">improve the guide</a>.</p> + +<p>{{PreviousMenuNext("Learn/HTML/Forms/Sending_forms_through_JavaScript", "Learn/HTML/Forms/Styling_HTML_forms", "Learn/HTML/Forms")}}</p> + +<p> </p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/HTML/Forms/Your_first_HTML_form">Your first HTML form</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/How_to_structure_an_HTML_form">How to structure an HTML form</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/The_native_form_widgets">The native form widgets</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Sending_and_retrieving_form_data">Sending form data</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Form_validation">Form data validation</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/How_to_build_custom_form_widgets">How to build custom form widgets</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Sending_forms_through_JavaScript">Sending forms through JavaScript</a></li> + <li>旧式浏览器中的HTML表单使用</li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Styling_HTML_forms">Styling HTML forms</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Advanced_styling_for_HTML_forms">Advanced styling for HTML forms</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Property_compatibility_table_for_form_widgets">Property compatibility table for form widgets</a></li> +</ul> + +<p> </p> diff --git a/files/zh-cn/learn/html/forms/index.html b/files/zh-cn/learn/html/forms/index.html new file mode 100644 index 0000000000..ad51eafa35 --- /dev/null +++ b/files/zh-cn/learn/html/forms/index.html @@ -0,0 +1,77 @@ +--- +title: HTML表单指南 +slug: Learn/HTML/Forms +tags: + - Forms + - HTML + - NeedsTranslation + - TopicStub +translation_of: Learn/Forms +--- +<div>{{LearnSidebar}}</div> + +<p class="summary">这个模块提供了一系列帮助您掌握HTML表单的文章。HTML表单是与用户交互的强大工具;然而,由于历史和技术上的原因,如何充分发挥它们的潜力并不总是显而易见的。在本指南中,我们将介绍HTML表单的所有方面,从结构到样式,从数据处理到自定义小部件。</p> + +<h2 id="预备知识">预备知识</h2> + +<p>在开始这个模块之前,您至少应该完成我们<a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML">对HTML的介绍</a>。此时此刻,您应该会发现{{anch("基本指南")}}很容易理解,并且能够使用我们的<a href="/zh-CN/docs/Learn/HTML/Forms/The_native_form_widgets">原生表单小部件</a>指南。</p> + +<p>但是模块的其余部分更高级一些,很容易将表单小部件放在页面上,但是如果不使用高级表单特性、CSS和JavaScript,就不能对它们做太多的工作。因此,在您查看其他部分之前,我们建议您先离开,先学习一些<a href="/zh-CN/docs/Learn/CSS">CSS</a>和<a href="/zh-CN/docs/Learn/JavaScript">JavaScript</a>。</p> + +<div class="note"> +<p><strong>注意:</strong>如果您正在使用一个不能让您创建自己的文件的计算机/平板电脑/其它设备,那么您可以尝试(大多数)在线编码程序中的代码示例,例如<a href="http://jsbin.com/">JSBin</a>或<a href="https://thimble.mozilla.org/">Thimble</a>。</p> +</div> + +<h2 id="基本指南">基本指南</h2> + +<dl> + <dt><a href="/zh-CN/docs/Learn/HTML/Forms/Your_first_HTML_form">你的第一个HTML表单</a></dt> + <dd>本系列的第一篇文章提供了您第一次创建HTML表单的经验,包括设计一个简单表单,使用正确的HTML元素实现它,通过CSS添加一些非常简单的样式,以及如何将数据发送到服务器。</dd> + <dt><a href="/zh-CN/docs/Learn/HTML/Forms/How_to_structure_an_HTML_form">如何构造HTML表单</a></dt> + <dd>有了基础知识,我们现在更详细地了解了用于为表单的不同部分提供结构和意义的元素。</dd> +</dl> + +<h2 id="什么表单小部件可用">什么表单小部件可用?</h2> + +<dl> + <dt><a href="/zh-CN/docs/Learn/HTML/Forms/The_native_form_widgets">原生表单小部件</a></dt> + <dd>现在,我们详细研究了不同表单部件的功能,查看了哪些选项可用于收集不同类型的数据。</dd> +</dl> + +<h2 id="验证和提交表单数据">验证和提交表单数据</h2> + +<dl> + <dt><a href="/zh-CN/docs/Learn/HTML/Forms/Sending_and_retrieving_form_data">发送表单数据</a></dt> + <dd>本文讨论当用户提交一个表单时,会发生什么情况——表单数据的去向以及当表单数据到达指定位置时我们如何处理?我们还研究了与发送表单数据相关的一些安全问题。</dd> + <dt><a href="/zh-CN/docs/Learn/HTML/Forms/Form_validation">表单数据验证</a></dt> + <dd>发送数据还不够,我们还需要确保数据用户填写表单的格式是正确的,我们需要成功地处理它,而且它不会破坏我们的应用程序。我们还希望帮助用户正确填写表单,在使用应用程序时不要感到沮丧。表单验证帮助我们实现这些目标,本文将告诉您需要了解的内容。</dd> +</dl> + +<h2 id="高级指南">高级指南</h2> + +<dl> + <dt><a href="/zh-CN/docs/Learn/HTML/Forms/How_to_build_custom_form_widgets">如何构建自定表单小组件</a></dt> + <dd>在某些情况下,原生表单部件无法提供您需要的东西,例如,由于样式或功能。在这种情况下,您可能需要使用原生HTML构建自己的表单小部件。本文将说明您是如何做到这一点的,以及在实际案例研究中需要注意的事项。</dd> + <dt><a href="/zh-CN/docs/Learn/HTML/Forms/Sending_forms_through_JavaScript">通过JavaScript发送表单</a></dt> + <dd>本文将讨论如何使用表单来组装HTTP请求,并通过定制的JavaScript发送它,而不是标准的表单提交。它还研究了为什么要这么做,以及这样做的意义。(请参阅使用FormData对象。)</dd> + <dt><a href="/zh-CN/docs/Learn/HTML/Forms/HTML_forms_in_legacy_browsers">遗留浏览器中的HTML表单</a></dt> + <dd>文章覆盖特性检测等。这应该被重定向到跨浏览器测试模块,因为相同的东西在那里被更好地覆盖。</dd> +</dl> + +<h2 id="表单样式指南">表单样式指南</h2> + +<dl> + <dt><a href="/zh-CN/docs/Learn/HTML/Forms/Styling_HTML_forms">HTML表单样式</a></dt> + <dd>本文介绍了使用CSS的样式表单,包括您可能需要了解的基本样式任务的所有基础知识。</dd> + <dt><a href="/zh-CN/docs/Learn/HTML/Forms/Advanced_styling_for_HTML_forms">高级HTML表单样式</a></dt> + <dd>在这里,我们将看到一些更高级的表单样式技术,这些技术需要在处理一些更难以风格的元素时使用。</dd> + <dt><a href="/zh-CN/docs/Learn/HTML/Forms/Property_compatibility_table_for_form_widgets">表单部件的属性兼容性表</a></dt> + <dd>这最后一篇文章提供了一个方便的参考,允许您查看哪些CSS属性与哪些表单元素是兼容的。</dd> +</dl> + +<h2 id="另见">另见</h2> + +<ul> + <li><a href="/zh-CN/docs/Web/HTML/Element#Forms">HTML forms element reference</a></li> + <li><a href="/zh-CN/docs/Web/HTML/Element/input">HTML <input> types reference</a></li> +</ul> diff --git a/files/zh-cn/learn/html/forms/property_compatibility_table_for_form_widgets/index.html b/files/zh-cn/learn/html/forms/property_compatibility_table_for_form_widgets/index.html new file mode 100644 index 0000000000..31f8075f5b --- /dev/null +++ b/files/zh-cn/learn/html/forms/property_compatibility_table_for_form_widgets/index.html @@ -0,0 +1,1988 @@ +--- +title: 表单组件兼容性列表 +slug: Learn/HTML/Forms/Property_compatibility_table_for_form_widgets +translation_of: Learn/Forms/Property_compatibility_table_for_form_controls +--- +<div>{{learnsidebar}}{{PreviousMenu("Learn/HTML/Forms/Advanced_styling_for_HTML_forms", "Learn/HTML/Forms")}}</div> + +<p class="summary">下面的兼容性表格尝试总结 HTML 表单的 CSS 支持状况。由于 CSS 和 HTML 表单的复杂性,不能把这些表格当作完善的参考。但是,它们可以让你很好地洞察什么能做什么不能做,这将会对你学习使用有很好地帮助。</p> + +<h2 id="如何阅读表格">如何阅读表格</h2> + +<h3 id="值">值</h3> + +<p>对于每个属性,有四种可能地取值:</p> + +<dl> + <dt>YES</dt> + <dd>此属性具有相当一致的跨浏览器支持。在某些极端情况下,你可能仍然会面临奇怪的副作用。</dd> + <dt>PARTIAL</dt> + <dd>尽管这个属性会生效,你还是会经常面对奇怪的副作用和不一致性。你应该尽力避免这些属性,除非你已经深知那些副作用。</dd> + <dt>NO</dt> + <dd>此属性就是不工作或者表现得非常不一致,所以并不可靠。</dd> + <dt>N.A.</dt> + <dd>此属性对这种类型的组件没有意义。</dd> +</dl> + +<h3 id="渲染">渲染</h3> + +<p>对于每个属性有两种可能的渲染方式:</p> + +<dl> + <dt>N (Normal)</dt> + <dd>表示这个属性会像设置的那样应用。</dd> + <dt>T (Tweaked)</dt> + <dd>表示这个属性需要通过下列的额外规则来使用:</dd> +</dl> + +<pre class="brush: css">* { +/* This turn off the native look and feel on WebKit based browsers */ + -webkit-appearance: none; + +/* This turn off the native look and feel on Gecko based browsers */ + -moz-appearance: none; + +/* This turn off the native look and feel on several different browsers + including Opera, Internet Explorer and Firefox */ + background: none; +}</pre> + +<h2 id="兼容性表格">兼容性表格</h2> + +<h3 id="Global_behaviors">Global behaviors</h3> + +<p>对许多浏览器来说,许多行为在全局范围内都是通用的:</p> + +<dl> + <dt>{{cssxref("border")}}, {{cssxref("background")}}, {{cssxref("border-radius")}}, {{cssxref("height")}}</dt> + <dd>任意属性可能影响组件部分或全部的原生外观。小心使用。</dd> + <dt>{{cssxref("line-height")}}</dt> + <dd>不同浏览器支持不同,避免使用</dd> + <dt>{{cssxref("text-decoration")}}</dt> + <dd>Opera表单不支持</dd> + <dt>{{cssxref("text-overflow")}}</dt> + <dd>Opera, Safari, IE9 表单不支持</dd> + <dt>{{cssxref("text-shadow")}}</dt> + <dd>Opera 和 IE9 不支持</dd> +</dl> + +<h3 id="Text_fields">Text fields</h3> + +<table> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">T</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>CSS box model</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1][2]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> + <ol> + <li>WebKit 浏览器 (主要在 Mac OSX and iOS 上) 的搜索域使用原生的样式和行为。因此,需要使用 <code>-webkit-appearance:none</code> 才能将这个属性应用到搜索域上。</li> + <li>在 Windows 7, Internet Explorer 9 不会应用到边框上,除非 <code>background:none</code> 已应用。</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1][2]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> + <ol> + <li>WebKit 浏览器 (主要在 Mac OSX and iOS 上) 的搜索域使用原生的样式和行为。因此,需要使用 <code>-webkit-appearance:none</code> 才能将这个属性应用到搜索域上。</li> + <li>在 Windows 7, Internet Explorer 9 不会应用到边框上,除非 <code>background:none</code> 已应用。</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1][2]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> + <ol> + <li>WebKit 浏览器 (主要在 Mac OSX and iOS 上) 的搜索域使用原生的样式和行为。因此,需要使用 <code>-webkit-appearance:none</code> 才能将这个属性应用到搜索域上。</li> + <li>在 Windows 7, Internet Explorer 9 不会应用到边框上,除非 <code>background:none</code> 已应用。</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Text and font</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}<sup>[1]</sup></th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> + <ol> + <li>如果 {{cssxref("border-color")}} 属性没有设置,一些基于 WebKit 的浏览器会将 {{cssxref("color")}} 属性应用到边框上,颜色和 {{HTMLElement("textarea")}} 的字体颜色一样。</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td>查看有关 {{cssxref("line-height")}} 的注释</td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td>查看有关 Opera 的注释</td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>IE9 只在 {{HTMLElement("textarea")}} 上支持这个属性,而 Opera 只在单行文本域中支持。</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Border and background</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> + <ol> + <li>WebKit 浏览器 (主要在 Mac OSX and iOS 上) 的搜索域使用原生的样式和行为。因此,需要使用 <code>-webkit-appearance:none</code> 才能将这个属性应用到搜索域上。</li> + <li>在 Windows 7上, Internet Explorer 9 不会应用到边框上,除非 <code>background:none</code> 已应用。</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1][2]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> + <ol> + <li>WebKit 浏览器 (主要在 Mac OSX and iOS 上) 的搜索域使用原生的样式和行为。因此,需要使用 <code>-webkit-appearance:none</code> 才能将这个属性应用到搜索域上。</li> + <li>在 Windows 7上, Internet Explorer 9 不会应用到边框上,除非 <code>background:none</code> 已应用。</li> + <li>在 Opera 上,只有当边框明确设定时 {{cssxref("border-radius")}} 属性才会应用</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>IE9 不支持这个属性</li> + </ol> + </td> + </tr> + </tbody> +</table> + +<h3 id="Buttons">Buttons</h3> + +<table> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">T</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>CSS box model</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> + <ol> + <li>这个属性不能应用于 Mac OSX or iOS 上基于 WebKit 的浏览器。</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> + <ol> + <li>这个属性不能应用于 Mac OSX or iOS 上基于 WebKit 的浏览器。</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Text and font</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td>查看{{cssxref("line-height")}} 的注意事项。</td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Border and background</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes<sup>[1]</sup></td> + <td> + <ol> + <li>在 Opera 上,只有当边框明确设定时 {{cssxref("border-radius")}} 属性才会应用</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>IE9 不支持这个属性</li> + </ol> + </td> + </tr> + </tbody> +</table> + +<h3 id="Number">Number</h3> + +<p>在实现了 <code>number</code> 组件的浏览器上,并没有一种标准的方式改变数字组件的样式,值得注意的是 Safari 上的数字输入框不在这个范围内。</p> + +<table> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">T</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>CSS box model</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>在 Opera 上,数字选择器缩小时,可能会隐藏域中内容。</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>在 Opera 上,数字选择器缩小时,可能会隐藏域中内容。</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Text and font</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td>查看{{cssxref("line-height")}} 的注意事项。</td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Border and background</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td colspan="1" rowspan="3"> + <p>支持,但浏览器之间的不一致性太多,所以并不可靠。</p> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + </tr> + </tbody> +</table> + +<h3 id="Check_boxes_and_radio_buttons">Check boxes and radio buttons</h3> + +<table> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">T</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>CSS box model</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td> + <ol> + <li>一些浏览器会添加额外的边缘,另一些会拉伸组件。</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td> + <ol> + <li>一些浏览器会添加额外的边缘,另一些会拉伸组件。</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Text and font</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Border and background</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + </tbody> +</table> + +<h3 id="Select_boxes_(single_line)">Select boxes (single line)</h3> + +<p>Firefox 不提供任何方式改变 {{HTMLElement("select")}} 元素的下箭头。</p> + +<table> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">T</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>CSS box model</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>这个属性在 {{HTMLElement("select")}} 元素上一切正常,但不能用于 {{HTMLElement("option")}} 或者 {{HTMLElement("optgroup")}} 元素。</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[2]</sup></td> + <td> + <ol> + <li>属性可以应用,但 Mac OSX 上浏览器之间的以不一致的方向显示,所以并不可靠。</li> + <li>这个属性在 {{HTMLElement("select")}} 元素上一切正常,但不能用于 {{HTMLElement("option")}} 或者 {{HTMLElement("optgroup")}} 元素。</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Text and font</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>在 Mac OSX 上, 基于 WebKit 的浏览器 不支持将这个属性用于原生组件。它们和 Opera, 在 {{HTMLElement("option")}} 和 {{HTMLElement("optgroup")}} 元素上根本不支持这个属性。</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>在 Mac OSX 上, 基于 WebKit 的浏览器 不支持将这个属性用于原生组件。它们和 Opera, 在 {{HTMLElement("option")}} 和 {{HTMLElement("optgroup")}} 元素上根本不支持这个属性。</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>IE9 不支持将这个属性用于 {{HTMLElement("select")}}, {{HTMLElement("option")}}, 和 {{HTMLElement("optgroup")}} 元素;Mac OSX 上基于 WebKit 的浏览器不支持将这个属性应用于 {{HTMLElement("option")}} 和 {{HTMLElement("optgroup")}} 元素。</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td> + <ol> + <li>Windows 7 上的 IE9 和 Mac OSX 上基于 WebKit 的浏览器,不支持这个组件上的这个属性。</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>只有 Firefox 提供了对这个属性的完全支持。Opera 根本不支持这个属性,而其他浏览器只提供了对 {{HTMLElement("select")}} 元素的支持。</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1][2]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1][2]</sup></td> + <td> + <ol> + <li>大部分浏览器仅仅支持将这个属性用于 {{HTMLElement("select")}} 元素。</li> + <li>IE9 不支持这个属性</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1][2]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1][2]</sup></td> + <td> + <ol> + <li>大部分浏览器仅仅支持将这个属性用于 {{HTMLElement("select")}} 元素。</li> + <li>IE9 不支持这个属性</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>大部分浏览器仅仅支持将这个属性用于 {{HTMLElement("select")}} 元素。</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Border and background</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td colspan="1" rowspan="3"> + <ol> + <li>大部分浏览器仅仅支持将这个属性用于 {{HTMLElement("select")}} 元素。</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + </tr> + </tbody> +</table> + +<h3 id="Select_boxes_(multiline)">Select boxes (multiline)</h3> + +<table> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">T</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>CSS box model</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>Opera 在 {{HTMLElement("select")}} 元素上 不支持 {{cssxref("padding-top")}} 和 {{cssxref("padding-bottom")}} 。</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Text and font</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td>查看{{cssxref("line-height")}} 的注意事项。</td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>IE9 在 {{HTMLElement("select")}}, {{HTMLElement("option")}}, 和{{HTMLElement("optgroup")}} 元素上不支持这个属性;Mac OSX 上基于 WebKit 的浏览器在 {{HTMLElement("option")}} 和{{HTMLElement("optgroup")}} 元素上不支持这个属性。</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td> + <ol> + <li>Windows 7 上的 IE9 和 Mac OSX 上基于 WebKit 的浏览器,不支持这个组件上的这个属性。</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td> + <ol> + <li>只被 Firefox and IE9+ 支持。</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>大部分浏览器仅仅支持将这个属性用于 {{HTMLElement("select")}} 元素。</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Border and background</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes<sup>[1]</sup></td> + <td> + <ol> + <li>在 Opera 上,只有当边框明确设定时 {{cssxref("border-radius")}} 属性才会应用</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>IE9 不支持这个属性</li> + </ol> + </td> + </tr> + </tbody> +</table> + +<h3 id="Datalist">Datalist</h3> + +<table> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">T</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>CSS box model</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Text and font</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Border and background</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + </tbody> +</table> + +<h3 id="File_picker">File picker</h3> + +<table> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">T</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>CSS box model</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Text and font</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td> + <ol> + <li>支持,但浏览器之间的不一致性太多,所以并不可靠。</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>许多浏览器将这个属性应用到选择按钮上。</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>它表现的或多或少的像一个组件左侧的边缘。</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Border and background</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td> + <ol> + <li>支持,但浏览器之间的不一致性太多,所以并不可靠。</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>IE9 不支持这个属性</li> + </ol> + </td> + </tr> + </tbody> +</table> + +<h3 id="Date_pickers">Date pickers</h3> + +<p>许多属性都支持但是浏览器之间的不一致性太多,所以并不可靠。</p> + +<table> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">T</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>CSS box model</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Text and font</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Border and background</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td> </td> + </tr> + </tbody> +</table> + +<h3 id="Color_pickers">Color pickers</h3> + +<p>There is currently not enough implementation to get realiable behaviors.</p> + +<table> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">T</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>CSS box model</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> + <ol> + <li>Opera 将它像一个选择组件一样,以同样的限制处理。</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> + <ol> + <li>Opera 将它像一个选择组件一样,以同样的限制处理。</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Text and font</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Border and background</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td colspan="1" rowspan="3"> + <ol> + <li>支持,但浏览器之间的不一致性太多,所以并不可靠。</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + </tr> + </tbody> +</table> + +<h3 id="Meters_and_progress">Meters and progress</h3> + +<p>There is currently not enough implementation to get realiable behaviors.</p> + +<table> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">T</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>CSS box model</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>当 {{cssxref("padding")}} 属性应用于一个 tweaked 元素时,Chrome 会隐藏 {{HTMLElement("progress")}} 和{{HTMLElement("meter")}} 元素。</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Text and font</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Border and background</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td colspan="1" rowspan="3"> + <ol> + <li>支持,但浏览器之间的不一致性太多,所以并不可靠。</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + </tr> + </tbody> +</table> + +<h3 id="Range">Range</h3> + +<p>There is no standard way to change the style of the range grip and Opera has no way to tweak the default rendering of the range widget.</p> + +<table> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">T</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>CSS box model</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>Chrome 和 Opera 在组件周围添加了一些额外的空白,而 Windows 7 上的 Opera 则拉伸范围选择器的滑块。</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> + <ol> + <li> {{cssxref("padding")}} 属性被运用,但是没有任何的视觉效果。</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Text and font</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Border and background</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td colspan="1" rowspan="3"> + <ol> + <li>支持,但浏览器之间的不一致性太多,所以并不可靠。</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + </tr> + </tbody> +</table> + +<h3 id="Image_buttons">Image buttons</h3> + +<table> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">T</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>CSS box model</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Text and font</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Border and background</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td colspan="1"> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td colspan="1"> + <ol> + <li>IE9 不支持这个属性</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td colspan="1"> + <ol> + <li>IE9 不支持这个属性</li> + </ol> + </td> + </tr> + </tbody> +</table> + +<p>{{PreviousMenu("Learn/HTML/Forms/Advanced_styling_for_HTML_forms", "Learn/HTML/Forms")}}</p> + +<p> </p> + +<h2 id="在本单元中">在本单元中</h2> + +<ul> + <li><a href="/en-US/docs/Learn/HTML/Forms/Your_first_HTML_form">Your first HTML form</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/How_to_structure_an_HTML_form">How to structure an HTML form</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/The_native_form_widgets">The native form widgets</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Sending_and_retrieving_form_data">Sending form data</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Form_validation">Form data validation</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/How_to_build_custom_form_widgets">How to build custom form widgets</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Sending_forms_through_JavaScript">Sending forms through JavaScript</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/HTML_forms_in_legacy_browsers">HTML forms in legacy browsers</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Styling_HTML_forms">Styling HTML forms</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Advanced_styling_for_HTML_forms">Advanced styling for HTML forms</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Property_compatibility_table_for_form_widgets">Property compatibility table for form widgets</a></li> +</ul> + +<p> </p> diff --git a/files/zh-cn/learn/html/forms/sending_and_retrieving_form_data/index.html b/files/zh-cn/learn/html/forms/sending_and_retrieving_form_data/index.html new file mode 100644 index 0000000000..ed3a4ef0ef --- /dev/null +++ b/files/zh-cn/learn/html/forms/sending_and_retrieving_form_data/index.html @@ -0,0 +1,369 @@ +--- +title: 发送表单数据 +slug: Learn/HTML/Forms/Sending_and_retrieving_form_data +tags: + - HTML + - HTTP + - Web + - request + - 安全 + - 表单 +translation_of: Learn/Forms/Sending_and_retrieving_form_data +--- +<p>{{LearnSidebar}}{{PreviousMenuNext("Learn/HTML/Forms/The_native_form_widgets", "Learn/HTML/Forms/Form_validation", "Learn/HTML/Forms")}}</p> + +<p class="summary">本文将讨论当用户提交表单时发生了什么——数据去了哪,以及当它到达时该如何处理?我们还研究了与发送表单数据相关的一些安全问题。</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">预备知识:</th> + <td> + <p>基本计算机素养,对<a href="/en-US/docs/Learn/HTML/Introduction_to_HTML">HTML的理解</a>,对<a href="/en-US/docs/Web/HTTP/Basics_of_HTTP">HTTP</a> 和<a href="/en-US/docs/Learn/Server-side/First_steps">服务器端编程</a>的基础知识。</p> + </td> + </tr> + <tr> + <th scope="row">目标:</th> + <td>了解表单数据提交时发生了什么,包括服务器上如何处理数据的基本概念。</td> + </tr> + </tbody> +</table> + +<h2 id="数据都去哪儿了?">数据都去哪儿了?</h2> + +<p>在这里,我们将讨论在提交表单时数据会发生什么。</p> + +<h3 id="客户端服务器体系结构">客户端/服务器体系结构</h3> + +<p>web基于非常基本的客户端/服务器体系结构,可以总结如下:客户端(通常是web浏览器)向服务器发送请求(大多数情况下是<a href="http://httpd.apache.org/" rel="external" title="http://httpd.apache.org/">Apache</a>、<a href="http://nginx.com/" rel="external" title="http://nginx.com/">Nginx</a>、<a href="http://www.iis.net/" rel="external" title="http://www.iis.net/">IIS</a>、<a href="http://tomcat.apache.org/" rel="external" title="http://tomcat.apache.org/">Tomcat</a>等web服务器),使用<a href="/en-US/docs/HTTP" title="/en-US/docs/HTTP">HTTP 协议</a>。服务器使用相同的协议来回答请求。</p> + +<p><img alt="A basic schema of the Web client/server architecture" src="/files/4291/client-server.png" style="display: block; height: 141px; margin: 0px auto; width: 400px;"></p> + +<p>在客户端,HTML表单只不过是一种方便的用户友好的方式,可以配置HTTP请求将数据发送到服务器。这使用户能够提供在HTTP请求中传递的信息。</p> + +<div class="note"> +<p><strong>注意:</strong>为了更好地了解客户端—服务器架构是如何工作的,请阅读我们的<a href="/en-US/docs/Learn/Server-side/First_steps">服务器端网站编程的第一个步骤</a>模块。</p> +</div> + +<h3 id="在客户端定义如何发送数据">在客户端:定义如何发送数据</h3> + +<p>{{HTMLElement("form")}}元素定义了如何发送数据。它的所有属性都是为了让您配置当用户点击提交按钮时发送的请求。两个最重要的属性是{{htmlattrxref("action","form")}}和{{htmlattrxref("method","form")}}。</p> + +<h4 id="htmlattrxref(actionform)_属性"> {{htmlattrxref("action","form")}} 属性</h4> + +<p>这个属性定义了发送数据要去的位置。它的值必须是一个有效的URL。如果没有提供此属性,则数据将被发送到包含这个表单的页面的URL。</p> + +<p>在这个例子中,数据被发送到一个绝对URL —— <code>http://foo.com</code>:</p> + +<pre class="brush: html"><form action="http://foo.com"></pre> + +<p class="brush: html">这里,我们使用相对URL——数据被发送到服务器上的不同URL</p> + +<pre class="brush: html"><form action="/somewhere_else"> +</pre> + +<p class="brush: html">在没有属性的情况下,像下面一样,{{HTMLElement("form")}}数据被发送到表单出现的相同页面上:</p> + +<pre class="brush: html"><form></pre> + +<p class="brush: html">许多较老的页面使用下面的符号表示数据应该被发送到包含表单的相同页面;这是必需的,因为直到HTML5{{htmlattrxref("action", "form")}}属性都需要该符号。现在,这不再需要了。</p> + +<pre class="brush: html"><form action="#"></pre> + +<div class="note"> +<p><strong>注意:</strong>可以指定使用HTTPS(安全HTTP)协议的URL。当您这样做时,数据将与请求的其余部分一起加密,即使表单本身是托管在使用HTTP访问的不安全页面上。另一方面,如果表单是在安全页面上托管的,但是您指定了一个不安全的HTTP URL,它带有{{htmlattrxref("action","form")}}属性,所有的浏览器都会在每次尝试发送数据时向用户显示一个安全警告,因为数据不会被加密。</p> +</div> + +<h4 id="htmlattrxref(methodform)属性"> {{htmlattrxref("method","form")}}属性</h4> + +<p>该属性定义了如何发送数据。<a href="/en-US/docs/HTTP">HTTP协议</a>提供了几种执行请求的方法;HTML表单数据可以通过许多不同的方法进行数据传输,其中最常见的是<code>GET</code>方法和<code>POST</code>方法。</p> + +<p>为了理解这两种方法之间的区别,让我们回过头来看看HTTP是如何工作的。<br> + 每当您想要访问Web上的资源时,浏览器都会向URL发送一个请求。<br> + HTTP请求由两个部分组成:一个包含关于浏览器功能的全局元数据集的头部,和一个包含服务器处理特定请求所需信息的主体。</p> + +<h5 id="GET_方法">GET 方法</h5> + +<p><code>GET</code>方法是浏览器使用的方法,请求服务器返回给定的资源:“嘿,服务器,我想要得到这个资源。”在这种情况下,浏览器发送一个空的主体。由于主体是空的,如果使用该方法发送一个表单,那么发送到服务器的数据将被追加到URL。</p> + +<p>考虑下面这个表单:</p> + +<pre class="brush: html"><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></pre> + +<p>由于已经使用了<code>GET</code>方法,当你提交表单的时候,您将看到<code>www.foo.com/?say=Hi&to=Mom</code>在浏览器地址栏里。</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14685/url-parameters.png" style="display: block; margin: 0 auto;">数据作为一系列的名称/值对被附加到URL。在URL web地址结束之后,我们得到一个问号(<code>?</code>),后面跟着由一个与符号(<code>&</code>)互相分隔开的名称/值对。在本例中,我们将两个数据传递给服务器。</p> + +<ul> + <li><code>say</code>, 它有一个 <code>Hi</code>的值。</li> + <li><code>to</code>, 它有一个 <code>Mom</code>的值。</li> +</ul> + +<p>HTTP请求如下:</p> + +<pre>GET /?say=Hi&to=Mom HTTP/2.0 +Host: foo.com</pre> + +<div class="note"> +<p><strong>注意:</strong>你可以在GitHub 上看到本例子——见 <a href="https://github.com/mdn/learning-area/blob/master/html/forms/sending-form-data/get-method.html">get-method.html</a> (<a href="https://mdn.github.io/learning-area/html/forms/sending-form-data/get-method.html">预览版</a>).</p> +</div> + +<h5 id="POST_方法">POST 方法</h5> + +<p><code>POST</code>方法略有不同。这是浏览器在询问响应时使用与服务器通信的方法,该响应考虑了HTTP请求正文中提供的数据:“嘿,服务器,看一下这些数据,然后给我回一个适当的结果。”如果使用该方法发送表单,则将数据追加到HTTP请求的主体中。</p> + +<p>让我们来看一个例子,这是我们在上面的<code>GET</code>部分中所看到的相同的形式,但是使用{{htmlattrxref("method","form")}}属性设置为<code>post</code>。</p> + +<pre class="brush: html"><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></pre> + +<p>当使用<code>POST</code>方法提交表单时,没有数据会附加到URL,HTTP请求看起来是这样的,而请求主体中包含的数据是这样的:</p> + +<pre>POST / HTTP/2.0 +Host: foo.com +Content-Type: application/x-www-form-urlencoded +Content-Length: 13 + +say=Hi&to=Mom</pre> + +<p><code>Content-Length</code>数据头表示主体的大小,<code>Content-Type</code>数据头表示发送到服务器的资源类型。稍后我们将讨论这些标头。</p> + +<div class="note"> +<p><strong>注意:</strong>你可以在 GitHub 上看到本例—— 见 <a href="https://github.com/mdn/learning-area/blob/master/html/forms/sending-form-data/post-method.html">post-method.html</a> (<a href="https://mdn.github.io/learning-area/html/forms/sending-form-data/post-method.html">预览版</a>).</p> +</div> + +<h4 id="查看HTTP请求">查看HTTP请求</h4> + +<p>HTTP请求永远不会显示给用户(如果您想要看到它们,您需要使用诸如<a href="/en-US/docs/Tools/Network_Monitor">Firefox Network Monitor</a>或<a href="https://developers.google.com/chrome-developer-tools/" title="https://developers.google.com/chrome-developer-tools/">Chrome Developer Tools</a>之类的工具)。例如,您的表单数据将显示在Chrome网络选项卡中:</p> + +<ol> + <li>按下 F12</li> + <li>选择 "Network"</li> + <li>选择 "All"</li> + <li>在 "Name" 标签页选择 "foo.com"</li> + <li>选择 "Headers"</li> +</ol> + +<p>你可以获得表单数据,像下图显示的那样</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14691/network-monitor.png" style="border-style: solid; border-width: 1px; display: block; margin: 0px auto;"></p> + +<p>唯一显示给用户的是被调用的URL。正如我们上面提到的,使用<code>GET</code>请求用户将在他们的URL栏中看到数据,但是使用<code>POST</code>请求用户将不会看到。这一点很重要,有两个原因:</p> + +<ol> + <li>如果您需要发送一个密码(或其他敏感数据),永远不要使用<code>GET</code>方法否则数据会在URL栏中显示,这将非常不安全。</li> + <li>如果您需要发送大量的数据,那么<code>POST</code>方法是首选的,因为一些浏览器限制了URL的大小。此外,许多服务器限制它们接受的URL的长度。</li> +</ol> + +<h3 id="在服务器端检索数据">在服务器端:检索数据</h3> + +<p>无论选择哪种HTTP方法,服务器都会接收一个字符串并解析,以便将数据作为键/值对序列获取。您访问这个序列的方式取决于您使用的开发平台以及您可能使用的任何特定框架。您使用的技术也决定了如何处理密钥副本;通常,最近收到的密钥的值是优先的。</p> + +<h4 id="例如:原始PHP">例如:原始PHP</h4> + +<p><a href="http://php.net/">PHP</a>提供了一些全局对象来访问数据。假设您已经使用了<code>POST</code>方法,那么下面的示例将获取数据并将其显示给用户。当然,你对数据的处理取决于你自己。您可以显示它,将它存储到数据库中,通过电子邮件发送它,或者以其他方式处理它。</p> + +<pre class="brush: php"><?php + // The global $_POST variable allows you to access the data sent with the POST method by name + // To access the data sent with the GET method, you can use $_GET + $say = htmlspecialchars($_POST['say']); + $to = htmlspecialchars($_POST['to']); + + echo $say, ' ', $to; +?></pre> + +<p>这个例子显示了一个带有我们发送的数据的页面。您可以在我们的示例<a href="https://github.com/mdn/learning-area/blob/master/html/forms/sending-form-data/php-example.html">php-example.html</a>中看到这一点——该文件包含与我们之前看到的相同的示例表单,它使用了<code>post</code>的<code>method</code>和<code>php-example.php</code>的<code>action</code>。当提交时,它将表单数据发送到<a href="https://github.com/mdn/learning-area/blob/master/html/forms/sending-form-data/php-example.php">php-example.php</a>,其中包含了上述代码块中所见的php代码。当执行此代码时,浏览器中的输出是<code>Hi Mom</code>。</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14693/php-result.png" style="display: block; margin: 0 auto;"></p> + +<div class="note"> +<p><strong>注意:</strong>当您将本例加载到本地浏览器中时,这个示例将无法工作---浏览器无法解析PHP代码,因此当提交表单时,浏览器只会为您提供下载PHP文件。为了让它生效,您需要通过某种类型的PHP服务器运行这个示例。本地PHP测试的好选择有<a href="https://www.mamp.info/en/downloads/">MAMP</a>(Mac和Windows)和<a href="http://ampps.com/download">AMPPS</a>(Mac、Windows、Linux)。</p> +</div> + +<h4 id="例子:_Python">例子: Python</h4> + +<p>这个例子展示了如何使用Python完成同样的事情——在web页面上显示提交的数据。<br> + 这将使用<a href="http://flask.pocoo.org/">Flask framework</a>来呈现模板、处理表单数据提交等(参见<a href="https://github.com/mdn/learning-area/blob/master/html/forms/sending-form-data/python-example.py">python-example.py</a>)。</p> + +<pre>from flask import Flask, render_template, request +app = Flask(__name__) + +@app.route('/', methods=['GET', 'POST']) +def form(): + return render_template('form.html') + +@app.route('/hello', methods=['GET', 'POST']) +def hello(): + return render_template('greeting.html', say=request.form['say'], to=request.form['to']) + +if __name__ == "__main__": + app.run()</pre> + +<p>以上代码中引用的两个模板如下:</p> + +<ul> + <li><a href="https://github.com/mdn/learning-area/blob/master/html/forms/sending-form-data/templates/form.html">form.html</a>: 与我们在{{anch("The POST method")}}小节中看到的相同的表单,但是将<code>action</code>设置为<code>\{{ url_for('hello') }}</code>。(这是一个<a href="http://jinja.pocoo.org/docs/2.9/">Jinja2</a>模板,它基本上是HTML,但是可以包含对运行包含在花括号中的web服务器的Python代码的调用。<code>url_for('hello')</code>基本上是在“提交表单时重定向到<code>/hello</code>”。</li> + <li><a href="https://github.com/mdn/learning-area/blob/master/html/forms/sending-form-data/templates/greeting.html">greeting.html</a>: 这个模板只包含一行,用于呈现渲染时传递给它的两个数据块。<br> + 这是通过前面所见的<code>hello()</code>函数完成的,该函数在<code>/hello</code>URL被导向时运行。</li> +</ul> + +<div class="note"> +<p><strong>注意:</strong>同样,如果您只是尝试将其直接加载到浏览器中,那么这段代码将无法工作。Python的工作方式与PHP略有不同——要在本地运行此代码,您需要<a href="/en-US/docs/Learn/Server-side/Django/development_environment#Installing_Python_3">安装Python/pip</a>,然后使用<code>pip3 install flask</code>安装Flask。此时,您应该能够使用<code>python3 python-example.py</code>来运行这个示例,然后在浏览器中导航到<code>localhost:5000</code>。</p> +</div> + +<h4 id="其他语言和框架">其他语言和框架</h4> + +<p>还有许多其他的服务器端技术可以用于表单处理,包括<a href="/en-US/docs/" title="/en-US/docs/">Perl</a>、<a href="/en-US/docs/" title="/en-US/docs/">Java</a>、 <a href="http://www.microsoft.com/net" title="http://www.microsoft.com/net">.Net</a>、<a href="/en-US/docs/" title="/en-US/docs/">Ruby</a>等。只挑你最喜欢的用就好。话虽如此,但值得注意的是,直接使用这些技术并不常见,因为这可能很棘手。更常见的是使用许多优秀的框架,这些框架使处理表单变得更容易,例如:</p> + +<ul> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django" rel="external">Django</a> for Python (比<a href="http://flask.pocoo.org/">Flask</a>要重量级一些,但是有更多的工具和选项。)</li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Express_Nodejs">Express</a> for Node.js</li> + <li><a href="https://laravel.com/">Laravel</a> for PHP</li> + <li><a href="https://rubyonrails.org/" rel="external">Ruby On Rails</a> for Ruby</li> + <li><a href="https://phoenixframework.org/">Phoenix</a> for Elixir</li> +</ul> + +<p>要注意的是,即使使用这些框架,使用表单也不一定很容易。但这比从头开始编写所有功能要简单得多,而且会节省很多时间。</p> + +<div class="note"> +<p><strong>注意:</strong>向您介绍任何服务器端语言或框架超出了本文的范围。如果你想要学习这些它们,上面的链接会给你一些帮助。</p> +</div> + +<h2 id="特殊案例发送文件">特殊案例:发送文件</h2> + +<p>用HTML表单发送文件是一个特殊的例子。文件是二进制数据——或者被认为是这样的——而所有其他数据都是文本数据。由于HTTP是一种文本协议,所以处理二进制数据有特殊的要求。</p> + +<h3 id="htmlattrxref(enctypeform)_属性">{{htmlattrxref("enctype","form")}} 属性</h3> + +<p>该属性允许您指定在提交表单时所生成的请求中的<code>Content-Type</code>的HTTP数据头的值。这个数据头非常重要,因为它告诉服务器正在发送什么样的数据。默认情况下,它的值是<code>application/x-www-form-urlencoded</code>。它的意思是:“这是已编码为URL参数的表单数据。”</p> + +<p>如果你想要发送文件,你需要额外的三个步骤:</p> + +<ul> + <li>将{{htmlattrxref("method","form")}}属性设置为<code>POST</code>,因为文件内容不能放入URL参数中。</li> + <li>将{{htmlattrxref("enctype","form")}}的值设置为<code>multipart/form-data</code>,因为数据将被分成多个部分,每个文件单独占用一个部分,表单正文中包含的文本数据(如果文本也输入到表单中)占用一个部分。</li> + <li>包含一个或多个<a href="/en-US/docs/Learn/HTML/Forms/The_native_form_widgets#File_picker">File picker</a>小部件,允许用户选择将要上传的文件。</li> +</ul> + +<p>例如:</p> + +<pre class="brush: html"><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></pre> + +<div class="note"> +<p><strong>注意:</strong>一些浏览器支持{{HTMLElement("input")}}的{{htmlattrxref("multiple","input")}}属性,它允许只用一个 <code><input></code> 元素选择一个以上的文件上传。服务器如何处理这些文件取决于服务器上使用的技术。如前所述,使用框架将使您的生活更轻松。</p> +</div> + +<div class="warning"> +<p><strong>警告:</strong>为了防止滥用,许多服务器配置了文件和HTTP请求的大小限制。在发送文件之前,先检查服务器管理员的权限是很重要的。</p> +</div> + +<h2 id="常见的安全问题">常见的安全问题</h2> + +<p>每次向服务器发送数据时,都需要考虑安全性。到目前为止,HTML表单是最常见的攻击路径(可能发生攻击的地方)。这些问题从来都不是来自HTML表单本身,它们来自于服务器如何处理数据。</p> + +<p>根据你所做的事情,你会遇到一些非常有名的安全问题:</p> + +<h3 id="XSS_和_CSRF">XSS 和 CSRF</h3> + +<p>跨站脚本(XSS)和跨站点请求伪造(CSRF)是常见的攻击类型,它们发生在当您将用户发送的数据显示给这个用户或另一个用户时。</p> + +<p>XSS允许攻击者将客户端脚本注入到其他用户查看的Web页面中。攻击者可以使用跨站点脚本攻击的漏洞来绕过诸如<a href="/en-US/docs/JavaScript/Same_origin_policy_for_JavaScript">同源策略</a>之类的访问控制。这些攻击的影响可能从一个小麻烦到一个重大的安全风险。</p> + +<p>CSRF攻击类似于XSS攻击,因为它们以相同的方式开始攻击——向Web页面中注入客户端脚本——但它们的目标是不同的。CSRF攻击者试图将权限升级到特权用户(比如站点管理员)的级别,以执行他们不应该执行的操作(例如,将数据发送给一个不受信任的用户)。</p> + +<p>XSS攻击利用用户对web站点的信任,而CSRF攻击则利用网站对其用户的信任。</p> + +<p>为了防止这些攻击,您应该始终检查用户发送给服务器的数据(如果需要显示),尽量不要显示用户提供的HTML内容。相反,您应该对用户提供的数据进行处理,这样您就不会逐字地显示它。当今市场上几乎所有的框架都实现了一个最小的过滤器,它可以从任何用户发送的数据中删除HTML{{HTMLElement("script")}}、{{HTMLElement("iframe")}} 和{{HTMLElement("object")}} 元素。这有助于降低风险,但并不一定会消除风险。</p> + +<h3 id="SQL注入">SQL注入</h3> + +<p>SQL 注入是一种试图在目标web站点使用的数据库上执行操作的攻击类型。这通常包括发送一个SQL请求,希望服务器能够执行它(通常发生在应用服务器试图存储由用户发送的数据时)。这实际上是<a href="https://www.owasp.org/index.php/Category:OWASP_Top_Ten_Project">攻击网站的主要途径之一</a>。 </p> + +<p>其后果可能是可怕的,从数据丢失到通过使用特权升级控制整个网站基础设施的攻击。这是一个非常严重的威胁,您永远不应该存储用户发送的数据,而不执行一些清理工作(例如,在php/mysql基础设施上使用<code><a href="http://www.php.net/manual/en/function.mysql-real-escape-string.php" rel="external" title="http://www.php.net/manual/en/function.mysql-real-escape-string.php">mysql_real_escape_string()</a></code>。</p> + +<h3 id="HTTP数据头注入和电子邮件注入">HTTP数据头注入和电子邮件注入</h3> + +<p>这种类型的攻击出现在当您的应用程序基于表单上用户的数据输入构建HTTP头部或电子邮件时。这些不会直接损害您的服务器或影响您的用户,但它们会引发一个更深入的问题,例如会话劫持或网络钓鱼攻击。</p> + +<p>这些攻击大多是无声的,并且可以将您的服务器变成<a href="http://en.wikipedia.org/wiki/Zombie_(computer_science)">僵尸</a>。</p> + +<h3 id="偏执永远不要相信你的用户">偏执:永远不要相信你的用户</h3> + +<p>那么,你如何应对这些威胁呢?这是一个远远超出本指南的主题,不过有一些规则需要牢记。最重要的原则是:永远不要相信你的用户,包括你自己;即使是一个值得信赖的用户也可能被劫持。</p> + +<p>所有到达服务器的数据都必须经过检查和消毒。总是这样。没有例外。</p> + +<ul> + <li>远离有潜在危险的字符转义。应该如何谨慎使用的特定字符取决于所使用的数据的上下文和所使用的服务器平台,但是所有的服务器端语言都有相应的功能。</li> + <li>限制输入的数据量,只允许有必要的数据。</li> + <li>沙箱上传文件(将它们存储在不同的服务器上,只允许通过不同的子域访问文件,或者通过完全不同的域名访问文件更好)。</li> +</ul> + +<p>如果你遵循这三条规则,你应该避免很多问题,但是如果你想要得到一个有能力的第三方执行的安全检查,这是一个好主意。不要以为你已经看到了所有可能的问题。</p> + +<div class="note"> +<p><strong>注意:</strong>我们的<a href="/en-US/docs/Learn/Server-side">服务器端</a>学习主题的<a href="/en-US/docs/Learn/Server-side/First_steps/Website_security">网站安全性文章</a>更详细地讨论了上述威胁和潜在的解决方案。</p> +</div> + +<h2 id="结论">结论</h2> + +<p>如您所见,发送表单数据很容易,但要确保应用程序的安全性是很棘手的。请记住,前端开发人员不是应该定义数据安全模型的人。是的,我们将看到,<a href="/en-US/docs/HTML/Forms/Data_form_validation">执行客户端数据验证</a>是可能的,但是服务器不能信任这种验证,因为它无法真正知道客户端到底发生了什么。</p> + +<h2 id="相关链接">相关链接</h2> + +<p>如果您想了解更多关于保护web应用程序的信息,您可以深入了解这些资源:</p> + +<ul> + <li><a href="/en-US/docs/Learn/Server-side/First_steps">Server-side website programming first steps</a></li> + <li><a href="https://www.owasp.org/index.php/Main_Page" rel="external" title="https://www.owasp.org/index.php/Main_Page">The Open Web Application Security Project (OWASP)</a></li> + <li><a href="http://shiflett.org/" rel="external" title="http://shiflett.org/">Chris Shiflett's blog about PHP Security</a></li> +</ul> + +<p>{{PreviousMenuNext("Learn/HTML/Forms/The_native_form_widgets", "Learn/HTML/Forms/Form_validation", "Learn/HTML/Forms")}}</p> + +<h2 id="在本单元中">在本单元中</h2> + +<ul> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Your_first_HTML_form">Your first HTML form</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/How_to_structure_an_HTML_form">How to structure an HTML form</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/The_native_form_widgets">The native form widgets</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Sending_and_retrieving_form_data">Sending form data</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Form_validation">Form data validation</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/How_to_build_custom_form_widgets">How to build custom form widgets</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Sending_forms_through_JavaScript">Sending forms through JavaScript</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/HTML_forms_in_legacy_browsers">HTML forms in legacy browsers</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Styling_HTML_forms">Styling HTML forms</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Advanced_styling_for_HTML_forms">Advanced styling for HTML forms</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Property_compatibility_table_for_form_widgets">Property compatibility table for form widgets</a></li> +</ul> diff --git a/files/zh-cn/learn/html/forms/sending_forms_through_javascript/index.html b/files/zh-cn/learn/html/forms/sending_forms_through_javascript/index.html new file mode 100644 index 0000000000..8489ff2243 --- /dev/null +++ b/files/zh-cn/learn/html/forms/sending_forms_through_javascript/index.html @@ -0,0 +1,439 @@ +--- +title: 使用 JavaScript 发送表单 +slug: Learn/HTML/Forms/Sending_forms_through_JavaScript +tags: + - HTML + - HTML表单 + - JavaScript + - Web 表单 + - 示例 + - 表单 + - 高级 +translation_of: Learn/Forms/Sending_forms_through_JavaScript +--- +<div>{{LearnSidebar}}{{PreviousMenuNext("Learn/HTML/Forms/How_to_build_custom_form_widgets", "Learn/HTML/Forms/HTML_forms_in_legacy_browsers", "Learn/HTML/Forms")}}</div> + +<p class="summary">正如在<a href="/en-US/docs/HTML/Forms/Sending_and_retrieving_form_data">前面的文章</a>中讲到的,HTML 表单可以声明式地发送一个 HTTP 请求。 但也可以通过 JavaScript 来为表单准备用于发送的 HTTP 请求。 本文探讨如何做到这一点。</p> + +<h2 id="表单不总是表单">表单不总是表单</h2> + +<p>在<a href="/en-US/docs/Open_Web_apps_and_Web_standards">开放式Web应用程序</a>中,使用 <a href="https://developer.mozilla.org/en-US/docs/HTML/Forms">HTML form</a> 而不是文字表单让人们来填写变得越来越普遍了 — 越来越多的开发人员正致力于控制传输数据。</p> + +<h3 id="获得整体界面的控制">获得整体界面的控制</h3> + +<p>标准的 HTML 表单提交会加载数据要发送到的URL,这意味着浏览器窗口以整页加载进行导航。 可以通过隐藏闪烁和网络滞后来避免整页加载以提供更平滑的体验。</p> + +<p>许多现代用户界面只使用HTML表单来收集用户的输入。 当用户尝试发送数据时,应用程序将在后台采取控制并且异步地传输数据,只更新UI中需要更改的部分。</p> + +<p>异步地发送任何数据被称为 <a href="/zh-CN/docs/AJAX" title="/zh-CN/docs/AJAX">AJAX</a>,它代表 "Asynchronous JavaScript And XML"。</p> + +<h3 id="表单提交和_AJAX_请求之间的区别">表单提交和 AJAX 请求之间的区别?</h3> + +<p>AJAX 技术主要依靠 {{domxref("XMLHttpRequest")}} (XHR) DOM 对象。它可以构造 HTTP 请求、发送它们,并获取请求结果。</p> + +<div class="note"> +<p><strong>注意:</strong> 老旧的 AJAX 技术可能不依赖 {{domxref("XMLHttpRequest")}}。例如 <a href="http://en.wikipedia.org/wiki/JSONP" rel="external">JSONP</a> 加 <a href="https://developer.mozilla.org/en-US/docs/Core_JavaScript_1.5_Reference:Global_Functions:eval"><code>eval()</code></a> 函数。这也行得通,但是有严重的安全问题,不推荐使用它。使用它的唯一原因是为了不支持 {{domxref("XMLHttpRequest")}} 或 <a href="https://developer.mozilla.org/en-US/docs/JSON">JSON</a>的过时浏览器;但是那些浏览器实在是太古老了!<strong>避免使用这种技术。</strong></p> +</div> + +<p>创建之初, {{domxref("XMLHttpRequest")}} 被设计用来将 <a href="/zh-CN/docs/XML" title="/zh-CN/docs/XML">XML</a> 作为传输数据的格式获取和发送。不过,如今 JSON 已经取代了 XML,而且要常用的多,无论这是不是一件好事。</p> + +<p>但是 XML 和 JSON 都不适合对表单数据请求编码。 表单数据(<code>application/x-www-form-urlencoded</code>)由 URL编码的键/值对列表组成。为了传输二进制数据,HTTP请求被重新整合成<code>multipart/form-data</code>形式。</p> + +<p>如果您控制前端(在浏览器中执行的代码)和后端(在服务器上执行的代码),则可以发送JSON / XML并根据需要处理它们。</p> + +<p>但是,如果你想使用第三方服务,没有那么简单。 有些服务只接受表单数据。 也有使用表单数据更简单的情况。 如果数据是键/值对,或是原始二进制数据,以现有的后端工具不需要额外的代码就可以处理它。</p> + +<p>那么如何发送这样的数据呢?</p> + +<h2 id="发送表单数据">发送表单数据</h2> + +<p>一共有三种方式来发送表单数据:包括两种传统的方法和一种利用 {{domxref("XMLHttpRequest/FormData","formData")}}对象的新方法.让我们仔细看一下:</p> + +<h3 id="构建_XMLHttpRequest">构建 XMLHttpRequest</h3> + +<p>{{domxref("XMLHttpRequest")}} 是进行 HTTP 请求的最安全和最可靠的方式。 要使用{{domxref("XMLHttpRequest")}}发送表单数据,请通过对其进行URL编码来准备数据,并遵守表单数据请求的具体细节。</p> + +<div class="note"> +<p><strong>备注:</strong>如果想要了解更多关于 <code>XMLHttpRequest</code> 的知识,你可能会对两篇文章感兴趣:<a href="/zh-CN/docs/AJAX/Getting_Started" title="/zh-CN/docs/AJAX/Getting_Started">An introductory article to AJAX</a> 和更高级点的<a href="/zh-CN/docs/DOM/XMLHttpRequest/Using_XMLHttpRequest" title="/zh-CN/docs/DOM/XMLHttpRequest/Using_XMLHttpRequest">using XMLHttpRequest</a>.</p> +</div> + +<p>让我们重建之前的这个例子:</p> + +<pre class="brush: html"><button type="button" onclick="sendData({test:'ok'})">点击我!</button></pre> + +<p>正如你所看到的,HTML实际上没什么改变。 不过,JavaScript变得截然不同了:</p> + +<pre class="brush: js">function sendData(data) { + var XHR = new XMLHttpRequest(); + var urlEncodedData = ""; + var urlEncodedDataPairs = []; + var name; + + // 将数据对象转换为URL编码的键/值对数组。 + for(name in data) { + urlEncodedDataPairs.push(encodeURIComponent(name) + '=' + encodeURIComponent(data[name])); + } + + // 将配对合并为单个字符串,并将所有%编码的空格替换为 + // “+”字符;匹配浏览器表单提交的行为。 + urlEncodedData = urlEncodedDataPairs.join('&').replace(/%20/g, '+'); + + // 定义成功数据提交时发生的情况 + XHR.addEventListener('load', function(event) { + alert('耶! 已发送数据并加载响应。'); + }); + + // 定义错误提示 + XHR.addEventListener('error', function(event) { + alert('哎呀!出问题了。'); + }); + + // 建立我们的请求 + XHR.open('POST', 'https://example.com/cors.php'); + + // 为表单数据POST请求添加所需的HTTP头 + XHR.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); + + // 最后,发送我们的数据。 + XHR.send(urlEncodedData); +}</pre> + +<p>在线演示:</p> + +<p>{{EmbedLiveSample("手动构建XMLHttpRequest", "100%", 50)}}</p> + +<div class="note"> +<p><strong>注:</strong> 当你想要往第三方网站传输数据时,使用{{domxref("XMLHttpRequest")}}会受到同源策略的影响。如果你需要执行跨域请求,你需要熟悉一下<a href="/zh-CN/docs/HTTP/Access_control_CORS" title="/zh-CN/docs/HTTP/Access_control_CORS">CORS和HTTP访问控制</a>.</p> +</div> + +<h3 id="使用_XMLHttpRequest_和_the_FormData_object(表单数据对象)">使用 XMLHttpRequest 和 the FormData object(表单数据对象)</h3> + +<p>手动建立一个 HTTP 请求非常困难。 幸运的是,最近的 <a href="http://www.w3.org/TR/XMLHttpRequest/">XMLHttpRequest 规范</a>提供了一种方便简单的方法 — 利用{{domxref("XMLHttpRequest/FormData","FormData")}}对象来处理表单数据请求。</p> + +<p>{{domxref("XMLHttpRequest/FormData","FormData")}} 对象可以用来构建用于传输的表单数据,或是获取表单元素中的数据来管理它的发送方式。 请注意,{{domxref("XMLHttpRequest/FormData","FormData")}} 对象是“只写”的,这意味着您可以更改它们,但不能检索其内容。</p> + +<p>使用这个对象在<a href="/en-US/docs/DOM/XMLHttpRequest/FormData/Using_FormData_Objects">Using FormData Objects</a>中有详细的介绍,不过这里有两个例子:</p> + +<h4 id="使用一个独立的_FormData_对象">使用一个独立的 FormData 对象</h4> + +<pre class="brush: html"><button type="button" onclick="sendData({test:'ok'})">点我!</button></pre> + +<p>你应该会觉得那个HTML示例很熟悉。</p> + +<pre class="brush: js">function sendData(data) { + var XHR = new XMLHttpRequest(); + var FD = new FormData(); + + // 把我们的数据添加到这个FormData对象中 + for(name in data) { + FD.append(name, data[name]); + } + + // 定义数据成功发送并返回后执行的操作 + XHR.addEventListener('load', function(event) { + alert('Yeah! 已发送数据并加载响应。'); + }); + + // 定义发生错误时执行的操作 + XHR.addEventListener('error', function(event) { + alert('Oops! 出错了。'); + }); + + // 设置请求地址和方法 + XHR.open('POST', 'https://example.com/cors.php'); + + // 发送这个formData对象,HTTP请求头会自动设置 + XHR.send(FD); +}</pre> + +<p>在线演示:</p> + +<p>{{EmbedLiveSample("向FormData对象中手动添加数据", "100%", 50)}}</p> + +<h4 id="使用绑定到表单元素上的_FormData">使用绑定到表单元素上的 FormData</h4> + +<p>你也可以把一个 <code>FormData</code> 对象绑定到一个 {{HTMLElement("form")}} 元素上。这会创建一个代表表单中包含元素的 <code>FormData</code> 。</p> + +<p>这段HTML是典型的情况:</p> + +<pre class="brush: html"><form id="myForm"> + <label for="myName">告诉我你的名字:</label> + <input id="myName" name="name" value="John"> + <input type="submit" value="提交"> +</form></pre> + +<p>但是 JavaScript 接管了这个表单:</p> + +<pre class="brush: js">window.addEventListener("load", function () { + function sendData() { + var XHR = new XMLHttpRequest(); + + // 我们把这个 FormData 和表单元素绑定在一起。 + var FD = new FormData(form); + + // 我们定义了数据成功发送时会发生的事。 + XHR.addEventListener("load", function(event) { + alert(event.target.responseText); + }); + + // 我们定义了失败的情形下会发生的事 + XHR.addEventListener("error", function(event) { + alert('哎呀!出了一些问题。'); + }); + + // 我们设置了我们的请求 + XHR.open("POST", "https://example.com/cors.php"); + + // 发送的数据是由用户在表单中提供的 + XHR.send(FD); + } + + // 我们需要获取表单元素 + var form = document.getElementById("myForm"); + + // ...然后接管表单的提交事件 + form.addEventListener("submit", function (event) { + event.preventDefault(); + + sendData(); + }); +});</pre> + +<p>在线演示:</p> + +<p>{{EmbedLiveSample("使用绑定到表单元素上的_FormData", "100%", 50)}}</p> + +<p>你甚至可以通过使用表单的{{domxref("HTMLFormElement.elements", "elements")}} 属性来更多的参与此过程,来得到一个包含表单里所有数据元素的列表,并且逐一手动管理他们。想了解更多,请参阅这里的例子:{{SectionOnPage("/en-US/docs/Web/API/HTMLFormElement.elements", "Accessing the element list's contents")}}</p> + +<h3 id="在隐藏的iframe中构建DOM">在隐藏的iframe中构建DOM</h3> + +<p>最古老的异步发送表单数据方法是用 DOM API 构建表单,然后将其数据发送到隐藏的 {{HTMLElement("iframe")}}。 要获得提交的结果,请获取{{HTMLElement("iframe")}}的内容。</p> + +<div class="warning"> +<p><strong>警告:</strong><strong>不要使用这项技术。</strong>有第三方服务的安全风险,因为它会使你暴露在 <a href="http://en.wikipedia.org/wiki/Cross-site_scripting" rel="external">脚本注入攻击</a> 中. 如果你使用 HTTPS,它会影响 <a href="https://developer.mozilla.org/en-US/docs/JavaScript/Same_origin_policy_for_JavaScript">同源策略</a>, 这可以使 {{HTMLElement("iframe")}} 内容无法访问。然而,该方法可能是你需要支持很古老的浏览器的唯一选择。</p> +</div> + +<p>下面是个简单的例子:</p> + +<pre class="brush: html"><button onclick="sendData({test:'ok'})">点击我!</button></pre> + +<p>所有操作都在下面这段脚本里:</p> + +<pre class="brush: js">// 首先创建一个用来发送数据的iframe. +var iframe = document.createElement("iframe"); +iframe.name = "myTarget"; + +// 然后,将iframe附加到主文档 +window.addEventListener("load", function () { + iframe.style.display = "none"; + document.body.appendChild(iframe); +}); + +// 下面这个函数是真正用来发送数据的. +// 它只有一个参数,一个由键值对填充的对象. +function sendData(data) { + var name, + form = document.createElement("form"), + node = document.createElement("input"); + + // 定义响应时发生的事件 + iframe.addEventListener("load", function () { + alert("Yeah! Data sent."); + }); + + form.action = "http://www.cs.tut.fi/cgi-bin/run/~jkorpela/echo.cgi"; + form.target = iframe.name; + + for(name in data) { + node.name = name; + node.value = data[name].toString(); + form.appendChild(node.cloneNode()); + } + + // 表单元素需要附加到主文档中,才可以被发送。 + form.style.display = "none"; + document.body.appendChild(form); + + form.submit(); + + // 表单提交后,就可以删除这个表单,不影响下次的数据发送。 + document.body.removeChild(form); +}</pre> + +<p>在线演示:</p> + +<p>{{EmbedLiveSample("在DOM中构建一个隐藏的iframe", "100%", 50)}}</p> + +<h2 id="处理二进制数据">处理二进制数据</h2> + +<p>如果你使用一个含有 <code><input type="file"></code> 组件的表格的 {{domxref("XMLHttpRequest/FormData","FormData")}} 对象,传给代码的数据会被自动处理。但是要手动发送二进制数据的话,还有额外的工作要做。</p> + +<p>在现代网络上,二进制数据有很多来源:例如{{domxref("FileReader")}} API、{{domxref("HTMLCanvasElement","Canvas")}} API、<a href="/zh-CN/docs/WebRTC/navigator.getUserMedia" title="/zh-CN/docs/WebRTC/navigator.getUserMedia">WebRTC</a> API,等等。不幸的是,一些过时的浏览器无法访问二进制数据,或是需要非常复杂的工作环境。这些遗留问题已经超出了本文的涵盖范围。如果你想了解更多关于 <code>FileReader</code> API的知识,参阅:<a href="/zh-CN/docs/Using_files_from_web_applications" title="/zh-CN/docs/Using_files_from_web_applications">如何在web应用程序中使用文件</a>。</p> + +<p>在 {{domxref("XMLHttpRequest/FormData","formData")}} 的帮助下,发送二进制数据非常简单,使用 <code>append()</code> 方法就可以了。如果你必须手动进行,那确实会有一些棘手。</p> + +<p>在下面的例子中,我们使用了{{domxref("FileReader")}} API来访问二进制数据,然后手动构建多重表单数据请求:</p> + +<pre class="brush: html"><form id="myForm"> + <p> + <label for="i1">文本数据:</label> + <input id="i1" name="myText" value="一些文本数据"> + </p> + <p> + <label for="i2">文件数据:</label> + <input id="i2" name="myFile" type="file"> + </p> + <button>提交!</button> +</form></pre> + +<p>如你所见,这个 HTML 只是一个标准的 <code><form></code>。没有什么神奇的事情发生。“魔法”都在 JavaScript 里:</p> + +<pre class="brush: js">// 因为我们想获取 DOM 节点, +// 我们在页面加载时初始化我们的脚本. +window.addEventListener('load', function () { + + // 这些变量用于存储表单数据 + var text = document.getElementById("i1"); + var file = { + dom : document.getElementById("i2"), + binary : null + }; + + // 使用 FileReader API 获取文件内容 + var reader = new FileReader(); + + // 因为 FileReader 是异步的, 会在完成读取文件时存储结果 + reader.addEventListener("load", function () { + file.binary = reader.result; + }); + + // 页面加载时, 如果一个文件已经被选择, 那么读取该文件. + if(file.dom.files[0]) { + reader.readAsBinaryString(file.dom.files[0]); + } + + // 如果没有被选择,一旦用户选择了它,就读取文件。 + file.dom.addEventListener("change", function () { + if(reader.readyState === FileReader.LOADING) { + reader.abort(); + } + + reader.readAsBinaryString(file.dom.files[0]); + }); + + // 发送数据是我们需要的主要功能 + function sendData() { + // 如果存在被选择的文件,等待它读取完成 + // 如果没有, 延迟函数的执行 + if(!file.binary && file.dom.files.length > 0) { + setTimeout(sendData, 10); + return; + } + + // 要构建我们的多重表单数据请求, + // 我们需要一个XMLHttpRequest 实例 + var XHR = new XMLHttpRequest(); + + // 我们需要一个分隔符来定义请求的每一部分。 + var boundary = "blob"; + + // 将我们的主体请求存储于一个字符串中 + var data = ""; + + // 所以,如果用户已经选择了一个文件 + if (file.dom.files[0]) { + // 在请求体中开始新的一部分 + data += "--" + boundary + "\r\n"; + + // 把它描述成表单数据 + data += 'content-disposition: form-data; ' + // 定义表单数据的名称 + + 'name="' + file.dom.name + '"; ' + // 提供文件的真实名字 + + 'filename="' + file.dom.files[0].name + '"\r\n'; + // 和文件的MIME类型 + data += 'Content-Type: ' + file.dom.files[0].type + '\r\n'; + + // 元数据和数据之间有一条空行。 + data += '\r\n'; + + // 将二进制数据添加到主体请求中 + data += file.binary + '\r\n'; + } + + // 文本数据更简单一些 + // 在主体请求中开始一个新的部分 + data += "--" + boundary + "\r\n"; + + // 声明它是表单数据,并命名它 + data += 'content-disposition: form-data; name="' + text.name + '"\r\n'; + // 元数据和数据之间有一条空行。 + data += '\r\n'; + + // 添加文本数据到主体请求中 + data += text.value + "\r\n"; + + // 一旦完成,“关闭”主体请求 + data += "--" + boundary + "--"; + + // 定义成功提交数据执行的语句 + XHR.addEventListener('load', function(event) { + alert('✌!数据已发送且响应已加载。'); + }); + + // 定义发生错误时做的事 + XHR.addEventListener('error', function(event) { + alert('哎呀!出现了一些问题。'); + }); + + // 建立请求 + XHR.open('POST', 'https://example.com/cors.php'); + + // 添加需要的HTTP头部来处理多重表单数据POST请求 + XHR.setRequestHeader('Content-Type','multipart/form-data; boundary=' + boundary); + + // 最后,发送数据。 + XHR.send(data); + } + + // 访问表单… + var form = document.getElementById("myForm"); + + // …接管提交事件 + form.addEventListener('submit', function (event) { + event.preventDefault(); + sendData(); + }); +});</pre> + +<p>在线演示:</p> + +<p>{{EmbedLiveSample("发送二进制数据", "100%", 150)}}</p> + +<h2 id="总结">总结</h2> + +<p>取决于不同的浏览器,通过 JavaScript 发送数据可能会很简单,也可能会很困难。{{domxref("XMLHttpRequest/FormData","FormData")}} 对象是通用的答案, 所以请毫不犹豫的在旧浏览器上通过polyfill使用它:</p> + +<ul> + <li>此<a href="https://gist.github.com/3120320" rel="external"> gist</a> 通过 {{domxref("Using_web_workers","Web Workers")}} polyfill 了 <code>FormData</code>。</li> + <li><a href="https://github.com/francois2metz/html5-formdata" rel="external">HTML5-formdata</a> 试图 polyfill <code>FormData</code> 对象, 但是它需要 <a href="http://www.w3.org/TR/FileAPI/" rel="external">File API</a></li> + <li>这个 <a href="https://github.com/jimmywarting/FormData">polyfill</a> 提供了 FormData 所有的大部分新方法(entries, keys, values, 以及对 <code>for...of</code> 的支持)</li> +</ul> + +<p>{{PreviousMenuNext("Learn/HTML/Forms/How_to_build_custom_form_widgets", "Learn/HTML/Forms/HTML_forms_in_legacy_browsers", "Learn/HTML/Forms")}}</p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/zh-CN/docs/Learn/HTML/Forms/Your_first_HTML_form">Your first HTML form</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Forms/How_to_structure_an_HTML_form">How to structure an HTML form</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Forms/The_native_form_widgets">The native form widgets</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Forms/Sending_and_retrieving_form_data">Sending form data</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Forms/Form_validation">Form data validation</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Forms/How_to_build_custom_form_widgets">How to build custom form widgets</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Forms/Sending_forms_through_JavaScript">Sending forms through JavaScript</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Forms/HTML_forms_in_legacy_browsers">HTML forms in legacy browsers</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Forms/Styling_HTML_forms">Styling HTML forms</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Forms/Advanced_styling_for_HTML_forms">Advanced styling for HTML forms</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Forms/Property_compatibility_table_for_form_widgets">Property compatibility table for form widgets </a></li> +</ul> diff --git a/files/zh-cn/learn/html/forms/styling_html_forms/index.html b/files/zh-cn/learn/html/forms/styling_html_forms/index.html new file mode 100644 index 0000000000..26b94e94e8 --- /dev/null +++ b/files/zh-cn/learn/html/forms/styling_html_forms/index.html @@ -0,0 +1,388 @@ +--- +title: 样式化 HTML 表单 +slug: Learn/HTML/Forms/Styling_HTML_forms +tags: + - CSS + - Web + - 例子 + - 指导 + - 样式 + - 表单 +translation_of: Learn/Forms/Styling_web_forms +--- +<p>{{LearnSidebar}}{{PreviousMenuNext("Learn/HTML/Forms/HTML_forms_in_legacy_browsers", "Learn/HTML/Forms/Advanced_styling_for_HTML_forms", "Learn/HTML/Forms")}}</p> + +<p class="summary">在这篇文章中,用户将学习如何使用HTML表单和CSS以使页面更加美观。令人惊讶的是,这可能有点棘手。由于历史和技术的原因,表单部件不能很好地与CSS配合工作。 由于这些困难,许多开发人员选择<a href="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets">构建自己的HTML小部件</a>以获得更好的控制和视觉观感。 然而,在现代浏览器中,web设计者越来越多地控制表单元素的设计。让我们深入研究。</p> + +<h2 id="为什么使用CSS美化表单组件这么困难?">为什么使用CSS美化表单组件这么困难?</h2> + +<p>在1995年左右的Web早期,表单组件(或控件)在 <a href="http://www.ietf.org/rfc/rfc1866.txt">HTML 2规范</a>中被添加到HTML。由于表单组件的复杂性,实现者选择依靠底层操作系统来管理和渲染它们。</p> + +<p>若干年后,CSS被创建出来了,那么技术上的必要性,就是使用原生组件来实现表单控制,这是因为风格的要求。在CSS的早期,表单样式控制不是优先事项。</p> + +<p>由于用户习惯于各自平台的视觉外观,浏览器厂商不愿意对表单控件样式进行调整;到目前为止,要重建所有控件以使它们可美化仍然是非常困难的。</p> + +<p>即使在今天,仍然没有一个浏览器完全实现了CSS 2.1。然而,随着时间的推移,浏览器厂商已经改进了对表单元素的CSS支持,尽管可用性的声誉不好,但现在已经可以使用CSS来设计<a href="/en-US/docs/HTML/Forms">HTML表单</a>。</p> + +<h3 id="涉及到CSS,并非所有组件都是平等的">涉及到CSS,并非所有组件都是平等的</h3> + +<p>目前,在使用表单时使用CSS仍然有一些困难。这些问题可以分为三类: </p> + +<h4 id="好的">好的</h4> + +<p>有些元素在跨平台上时很少出现问题。包括以下结构元素:</p> + +<ol> + <li>{{HTMLElement("form")}}</li> + <li>{{HTMLElement("fieldset")}}</li> + <li>{{HTMLElement("label")}}</li> + <li>{{HTMLElement("output")}}</li> +</ol> + +<p>这还包括所有文本字段小部件(单行和多行)和按钮。</p> + +<h4 id="不好的">不好的</h4> + +<p>一些元素难以被美化,并且可能需要一些复杂的技巧,偶尔需要高级的CSS3知识。</p> + +<p>这些包括{{HTMLElement("legend")}}元素,但不能在所有平台上正确定位。 Checkbox和radio按钮也不能直接应用样式,但是,感谢CSS3,你可以解决这个问题。{{htmlattrxref("placeholder", "input")}} 的内容不能以任何标准方式应用样式,但是实现它的所有浏览器也都实现了私有的CSS伪元素或伪类,让你可以对其定义样式。</p> + +<p>我们会在<a href="https://developer.mozilla.org/zh-CN/docs/Learn/HTML/Forms/How_to_build_custom_form_widgets">如何构建自定义表单挂件</a>一文中讲述如何处理更多特定的问题。</p> + +<h4 id="丑陋的">丑陋的</h4> + +<p>有些元素根本不能用应用CSS样式。 这些包括:所有高级用户界面小部件,如范围,颜色或日期控件; 和所有下拉小部件,包括{{HTMLElement("select")}}, {{HTMLElement("option")}}, {{HTMLElement("optgroup")}}和{{HTMLElement("datalist")}} 元素。 文件选择器小部件也被称为不可样式化。 新的{{HTMLElement("progress")}}和{{HTMLElement("meter")}} 元素也属于这个类别。</p> + +<p>所有这些小部件的主要问题来自于它们具有非常复杂的结构,而CSS目前还不足以表达这些小部件的所有细微部分。 如果你想定制这些小部件,你必须依靠JavaScript来构建一个你能够应用样式的DOM树。我们会在 <a href="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets" title="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets">How to build custom form widgets</a>一文中探索如何实现这一点。</p> + +<h2 id="基本样式美化">基本样式美化</h2> + +<p>为了使用CSS美化容易被美化的元素,你并不会碰到任何困难,因为它们的大部分行为同其他HTML元素差不多。但是,每个浏览器的用户代理样式表可能会有点不一致,所以有一些技巧可以帮助您更轻松地设计它们。</p> + +<h3 id="Search字段">Search字段</h3> + +<p>搜索框是唯一一种应用CSS样式有点棘手的文本字段。 在基于WebKit的浏览器(Chrome,Safari等)上,您必须使用<code>-webkit-appearance</code>专有属性来调整它。 我们在文章中进一步讨论这个属性:<a href="/en-US/docs/Advanced_styling_for_HTML_forms">HTML表单的高级样式</a>。</p> + +<h4 id="Example">Example</h4> + +<pre class="brush: html"><form> + <input type="search"> +</form> +</pre> + +<pre class="brush: css">input[type=search] { + border: 1px dotted #999; + border-radius: 0; + + -webkit-appearance: none; +}</pre> + +<p><img alt="This is a screenshot of a search filed on Chrome, with and without the use of -webkit-appearance" src="/files/4153/search-chrome-macos.png" style="border-style: solid; border-width: 1px; height: 107px; width: 179px;"></p> + +<p>截图中是 Chrome 浏览器中的两个搜索框,在我们的例子中,两个搜索框均被设置为有边框。第一个没有使用<code>-webkit-appearance</code>渲染,而第二个使用了 <code>-webkit-appearance:none</code>. 两者的不同显而易见。</p> + +<h3 id="字体和文本">字体和文本</h3> + +<p>CSS font和text功能能被很容易的应用到任何组件上(当然你可以在form组件上使用{{cssxref("@font-face")}} )。然而,浏览器的行为经常不一致。默认情况下,一些组件不会从它们的父元素继承 {{cssxref("font-family")}}和 {{cssxref("font-size")}} 。相反,许多浏览器使用系统默认的字体和文本。为了让form表单的外观和其他内容保持一致,你可以在你的样式表中增加以下内容:</p> + +<pre class="brush: css">button, input, select, textarea { + font-family : inherit; + font-size : 100%; +}</pre> + +<p>下面的截图显示了不同之处; 左边是Mac OS X上Firefox中元素的默认渲染,其中使用了平台的默认字体样式。 在右边是相同的元素,应用了我们的字体统一样式规则。</p> + +<p><img alt="This is a screenshot of the main form widgets on Firefox on Mac OSX, with and without font harmonization" src="/files/4157/font-firefox-macos.png" style="border-style: solid; border-width: 1px; height: 234px; width: 420px;"></p> + +<p>关于使用系统默认样式的表单还是使用设计用于匹配内容的自定义样式表单,有很多争议。 作为网站或Web应用程序的设计者,您可以自己做出决定。</p> + +<h3 id="盒子模型">盒子模型</h3> + +<p>所有文本字段都完全支持与CSS盒模型相关的每个属性({{cssxref("width")}}, {{cssxref("height")}}, {{cssxref("padding")}}, {{cssxref("margin")}}, 和 {{cssxref("border")}})。 但是,像以前一样,浏览器在显示这些小部件时依赖于系统默认的样式。 您需要定义如何将其融入到您的内容中。 如果你既想保持小部件的原生外观和感觉,又想给他们一个一致的尺寸,那么你会遇到一些困难(如果你想保持组件的原生观感,又想给它们一致的大小,你会面临一些困难)。</p> + +<p><strong>这是因为每个小部件都有自己的边框,填充和边距的规则。</strong> 所以如果你想给几个不同的小部件相同的大小,你必须使用{{cssxref("box-sizing")}} 属性:</p> + +<pre class="brush: css">input, textarea, select, button { + width : 150px; + margin: 0; + + -webkit-box-sizing: border-box; /* For legacy WebKit based browsers */ + -moz-box-sizing: border-box; /* For legacy (Firefox <29) Gecko based browsers */ + box-sizing: border-box; +}</pre> + +<p><img alt="This is a screenshot of the main form widgets on Chrome on Windows 7, with and without the use of box-sizing." src="/files/4161/size-chrome-win7.png" style="border-style: solid; border-width: 1px; height: 213px; width: 358px;"></p> + +<p>在上面的屏幕截图中,左侧的列没有{{cssxref("box-sizing")}},而右侧的列使用了这个属性和<code>border-box</code>。 请注意我们是怎样确保所有元素都占用相同的空间量,尽管平台对每种窗口小部件都有默认规则。</p> + +<h3 id="定位(Positioning)">定位(Positioning)</h3> + +<p>HTML表单部件的定位通常不是问题; 但是,您应该特别注意两点:</p> + +<h4 id="legend">legend</h4> + +<p>{{HTMLElement("legend")}}元素易于应用CSS,除了定位。在所有浏览器中, {{HTMLElement("legend")}} 元素定位是其 {{HTMLElement("fieldset")}} 父元素的上边框的最顶端。在HTML流中无法改变它的绝对位置,无法让其远离顶部边框。然而,你可以使用 {{cssxref("position")}} 属性将其位置设置为绝对或相对。除此之外,它近几年是fieldset边框的一部分。</p> + +<p>由于{{HTMLElement("legend")}}元素对可访问性非常重要,因为它能被无障碍技术作为每个fieldset中的表单元素的标签读出来,它通常与标题配对,并且在无障碍中被隐藏 。例如:</p> + +<h5 id="HTML">HTML</h5> + +<pre class="brush: html"><fieldset> + <legend>Hi!</legend> + <h1>Hello</h1> +</fieldset></pre> + +<h5 id="CSS">CSS</h5> + +<pre class="brush: css">legend { + width: 1px; + height: 1px; + overflow: hidden; +}</pre> + +<h4 id="textarea">textarea</h4> + +<p>默认情况下,所有浏览器都认为{{HTMLElement("textarea")}} 元素是inline block,与文本底线对齐。 这很少是我们真正想看到的。 要将内联(<code>inline-block</code>)块更改为块(<code>block</code>),使用{{cssxref("display")}}属性非常简单。 但是如果你想以inline方式使用它,通常改变垂直对齐方式:</p> + +<pre class="brush: css">textarea { + vertical-align: top; +}</pre> + +<h2 id="示例">示例</h2> + +<p>让我们来看一个样式化 HTML 表单的实际的案例。这有助于理清这里面的许多概念。我们将构建下面的"明信片" 联系人表单:</p> + +<p><img alt="This is what we want to achieve with HTML and CSS" src="/files/4149/screenshot.png" style="border-style: solid; border-width: 1px; height: 249px; width: 370px;"></p> + +<p>如果你想继续关注这个例子,复制我们的 <a href="https://github.com/mdn/learning-area/blob/master/html/forms/postcard-example/postcard-start.html">postcard-start.html</a> 文件,并遵循接下来的指导操作。</p> + +<h3 id="The_HTML">The HTML</h3> + +<p>HTML 只比我们在 <a href="/en-US/docs/HTML/Forms/My_first_HTML_form" title="/en-US/docs/HTML/Forms/My_first_HTML_form">the first article of this guide</a> 中涉及到的多一些;它只有一些额外的 id 和 title。</p> + +<pre class="brush: html"><form> + <h1>to: Mozilla</h1> + + <div id="from"> + <label for="name">from:</label> + <input type="text" id="name" name="user_name"> + </div> + + <div id="reply"> + <label for="mail">reply:</label> + <input type="email" id="mail" name="user_email"> + </div> + + <div id="message"> + <label for="msg">Your message:</label> + <textarea id="msg" name="user_message"></textarea> + </div> + + <div class="button"> + <button type="submit">Send your message</button> + </div> +</form></pre> + +<p>将上面的代码添加到你 HTML 的 body 中。</p> + +<h3 id="组织你的静态文件">组织你的静态文件</h3> + +<p>好戏要开始了! 在开始写代码之前,我们需要三个额外的静态文件:</p> + +<ol> + <li>明信片的<a href="/files/4151/background.jpg" title="The postcard background">背景</a>——下载这幅图片,把它和你的 HTML 文件保存在相同目录下。</li> + <li>打字机字体:<a href="http://www.fontsquirrel.com/fonts/Secret-Typewriter" rel="external" title="http://www.fontsquirrel.com/fonts/Secret-Typewriter">源自 fontsquirrel.com 的 "Secret Typewriter“ 字体</a>——将TTF文件下载到和上面相同的文件夹里。</li> + <li>手绘字体:<a href="http://www.fontsquirrel.com/fonts/Journal" rel="external" title="http://www.fontsquirrel.com/fonts/Journal">源自 fontsquirrel.com 的 The "Journal" 字体 </a> —— 将TTF文件下载到和上面相同的文件夹里。</li> +</ol> + +<p>在你开始之前需要对字体做一些处理:</p> + +<ol> + <li>打开 fontsquirrel <a href="https://www.fontsquirrel.com/tools/webfont-generator">网络字体生成器</a>.</li> + <li>使用表单,上传你的字体文件并生成一个网络字体包,将这个包下载到你的电脑上。</li> + <li>解压提供的 zip 文件。</li> + <li>再解压后的文件内容里你会找到两个 <code>.woff</code> 文件和两个<code>.woff2</code> 文件。将这四个文件拷贝到一个叫 fonts 的文件夹里,而fonts 文件夹位于和上面相同的文件夹里。我们为每种字体使用两个不同的文件以最大限度地保证浏览器兼容性。查看我们的 <a href="/en-US/docs/Learn/CSS/Styling_text/Web_fonts">Web 字体</a> 一文获取更多信息。</li> +</ol> + +<h3 id="CSS_2">CSS</h3> + +<p>现在我们可以深入探究本例的 CSS 了。将下面所有的代码块一个接一个地加到{{htmlelement("style")}} 元素里。</p> + +<p>首先,我们要准备一些基础。这需要定义 {{cssxref("@font-face")}} 规则,以及所有的 {{HTMLElement("body")}} 元素和 {{HTMLElement("form")}} 元素基本规则:</p> + +<pre class="brush: css">@font-face { + font-family: 'handwriting'; + src: url('fonts/journal-webfont.woff2') format('woff2'), + url('fonts/journal-webfont.woff') format('woff'); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'typewriter'; + src: url('fonts/veteran_typewriter-webfont.woff2') format('woff2'), + url('fonts/veteran_typewriter-webfont.woff') format('woff'); + font-weight: normal; + font-style: normal; +} + +body { + font : 21px sans-serif; + + padding : 2em; + margin : 0; + + background : #222; +} + +form { + position: relative; + + width : 740px; + height : 498px; + margin : 0 auto; + + background: #FFF url(background.jpg); +}</pre> + +<p>现在我们可以定位我们的元素,包括标题和其他表单元素:</p> + +<pre class="brush: css">h1 { + position : absolute; + left : 415px; + top : 185px; + + font : 1em "typewriter", sans-serif; +} + +#from { + position: absolute; + left : 398px; + top : 235px; +} + +#reply { + position: absolute; + left : 390px; + top : 285px; +} + +#message { + position: absolute; + left : 20px; + top : 70px; +}</pre> + +<p>现在我们开始处理表单元素本身。首先,让我们确保 {{HTMLElement("label")}} 被赋予了正确的字体:</p> + +<pre class="brush: css">label { + font : .8em "typewriter", sans-serif; +}</pre> + +<p>文本域需要一些通用的规则,我们只需简单的移除 {{cssxref("border","borders")}} 和 {{cssxref("background","backgrounds")}}, 并重新定义其{{cssxref("padding")}} 和 {{cssxref("margin")}}:</p> + +<pre class="brush: css">input, textarea { + font : .9em/1.5em "handwriting", sans-serif; + + border : none; + padding : 0 10px; + margin : 0; + width : 240px; + + background: none; +}</pre> + +<p>当其中的一个域获得焦点后,我们用浅灰色、半透明的背景高亮它们,注意添加{{cssxref("outline")}} 属性非常重要,这样可以移除由某些浏览器添加的默认高亮效果:</p> + +<pre class="brush: css">input:focus, textarea:focus { + background : rgba(0,0,0,.1); + border-radius: 5px; + outline : none; +}</pre> + +<p>现在我们的文本域已经完成了,我们需要调整单行和多行文本域的显示,使其能够匹配,因为通常情况下它们不会以默认的设置而具有一样的外观。</p> + +<p>单行文本需要一些调整才能在 Internet Explorer 中渲染良好。Internet Explorer 没有基于字体的自然高度来定义文本域的高度(而这是所有其他浏览器都有的行为)。为了修正这个问题,我们需要给域添加一个确定的高度,像下面这样:</p> + +<pre class="brush: css">input { + height: 2.5em; /* for IE */ + vertical-align: middle; /* This is optional but it makes legacy IEs look better */ +}</pre> + +<p>{{HTMLElement("textarea")}} 元素默认地被渲染成一个块级元素。这里有重要地两点是 {{cssxref("resize")}} 和 {{cssxref("overflow")}} 属性。因为我们的设计是一个固定大小的设计,所以我们会使用 <code>resize</code> 属性来防止用户调整我们的多行文本域的大小。{{cssxref("overflow")}} 属性是用来让域在不同的浏览器上渲染得更一致。一些浏览器默认值为 <code>auto</code>,而一些将默认值设为 <code>scroll</code>。在我们得例子中,最好确定每个浏览器都使用 <code>auto</code>:</p> + +<pre class="brush: css">textarea { + display : block; + + padding : 10px; + margin : 10px 0 0 -10px; + width : 340px; + height : 360px; + + resize : none; + overflow: auto; +}</pre> + +<p>{{HTMLElement("button")}} 元素上使用 CSS 非常方便;你可以做你任何想做得事情,甚至包括使用 <a href="/en-US/docs/CSS/Pseudo-elements" title="/en-US/docs/CSS/Pseudo-elements">伪元素</a>:</p> + +<pre class="brush: css">button { + position : absolute; + left : 440px; + top : 360px; + + padding : 5px; + + font : bold .6em sans-serif; + border : 2px solid #333; + border-radius: 5px; + background : none; + + cursor : pointer; + +-webkit-transform: rotate(-1.5deg); + -moz-transform: rotate(-1.5deg); + -ms-transform: rotate(-1.5deg); + -o-transform: rotate(-1.5deg); + transform: rotate(-1.5deg); +} + +button:after { + content: " >>>"; +} + +button:hover, +button:focus { + outline : none; + background: #000; + color : #FFF; +}</pre> + +<p>瞧!</p> + +<div class="note"> +<p><strong>注意:如果你的例子没有像你预期的那样工作,你想将它同我们的版本检查对比,</strong>你可以在Github 上找到它 —— 查看 <a href="https://mdn.github.io/learning-area/html/forms/postcard-example/">在线演示</a> (也可以查看<a href="https://github.com/mdn/learning-area/tree/master/html/forms/postcard-example">源代码</a>)。</p> +</div> + +<h2 id="总结">总结</h2> + +<p>如你所见,若我们想构建只包含文本域和按钮的表单,用 CSS 美化它们非常容易。如果你想要知道更多能够让你的处理表单组件时更轻松的 CSS 小技巧,看一看 <a href="http://necolas.github.com/normalize.css" rel="external" title="http://necolas.github.com/normalize.css">normalize.css </a>项目的表单部分。</p> + +<p><a href="/en-US/docs/Web/Guide/HTML/Forms/Advanced_styling_for_HTML_forms" title="/en-US/docs/Advanced_styling_for_HTML_forms">下一篇文章中</a>,我们将会看到如何处理落入"不好的" 和"丑陋的" 分类的表单组件。</p> + +<p>{{PreviousMenuNext("Learn/HTML/Forms/HTML_forms_in_legacy_browsers", "Learn/HTML/Forms/Advanced_styling_for_HTML_forms", "Learn/HTML/Forms")}}</p> + +<h2 id="在本单元中">在本单元中</h2> + +<ul> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Your_first_HTML_form">Your first HTML form</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/How_to_structure_an_HTML_form">How to structure an HTML form</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/The_native_form_widgets">The native form widgets</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Sending_and_retrieving_form_data">Sending form data</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Form_validation">Form data validation</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/How_to_build_custom_form_widgets">How to build custom form widgets</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Sending_forms_through_JavaScript">Sending forms through JavaScript</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/HTML_forms_in_legacy_browsers">HTML forms in legacy browsers</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Styling_HTML_forms">Styling HTML forms</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Advanced_styling_for_HTML_forms">Advanced styling for HTML forms</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Property_compatibility_table_for_form_widgets">Property compatibility table for form widgets</a></li> +</ul> diff --git a/files/zh-cn/learn/html/forms/the_native_form_widgets/index.html b/files/zh-cn/learn/html/forms/the_native_form_widgets/index.html new file mode 100644 index 0000000000..8ef67a2f7a --- /dev/null +++ b/files/zh-cn/learn/html/forms/the_native_form_widgets/index.html @@ -0,0 +1,683 @@ +--- +title: 原生表单部件 +slug: Learn/HTML/Forms/The_native_form_widgets +translation_of: Learn/Forms/Basic_native_form_controls +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/HTML/Forms/How_to_structure_an_HTML_form", "Learn/HTML/Forms/Sending_and_retrieving_form_data", "Learn/HTML/Forms")}}</div> + +<p class="summary">现在,我们将详细研究不同表单部件的功能,查看了哪些选项可用于收集不同类型的数据。这个指南有些详尽,涵盖了所有可用的原生表单小部件。</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">预备知识:</th> + <td>计算机基础知识和对于<a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Introduction_to_HTML">HTML的基本理解</a>。</td> + </tr> + <tr> + <th scope="row">目标:</th> + <td>要了解在浏览器中可以使用什么类型的原生表单小部件来收集数据,以及如何使用HTML实现它们。</td> + </tr> + </tbody> +</table> + +<p>这里我们将关注浏览器内置的表单部件,但是因为HTML表单仍然相当有限并且实现的特性在不同的浏览器中可能是相当不同的,web开发人员有时会建立自己的表单部件——关于这个的更多想法,参见本模块后面的<a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/How_to_build_custom_form_widgets">如何构建自定义表单部件</a>。</p> + +<div class="note"> +<p><strong>译者注:</strong>widget在本页面中被统一翻译为部件,但在其他地方可能也被译为组件。</p> +</div> + +<div class="note"> +<p><strong>注意:</strong>本文中讨论的大多数特性都在浏览器中得到了广泛的支持;我们会注意到例外的情况。如果您想要更准确的细节,您应该参考我们的<a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element#Forms">HTML表单元素参考</a>,特别是我们的广泛的 <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input"><input></a>类型参考。</p> +</div> + +<h2 id="通用属性">通用属性</h2> + +<p>大部分用来定义表单小部件的元素都有一些他们自己的属性。然而,在所有表单元素中都有一组通用属性,它们可以对这些小部件进行控制。下面是这些通用属性的列表:</p> + +<table> + <thead> + <tr> + <th scope="col">属性名称</th> + <th scope="col">默认值</th> + <th scope="col">描述</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>autofocus</code></td> + <td>(<em>false</em>)</td> + <td>这个布尔属性允许您指定当页面加载时元素应该自动具有输入焦点,除非用户覆盖它,例如通过键入不同的控件。文档中只有一个与表单相关的元素可以指定这个属性。</td> + </tr> + <tr> + <td><code>disabled</code></td> + <td>(<em>false</em>)</td> + <td> + <p>这个布尔属性表示用户不能与元素交互。如果没有指定这个属性,元素将从包含它的元素继承设置,例如{{HTMLElement("fieldset")}};如果没有包含在设定了<code>disabled</code>属性的元素里,那么这个元素就是可用的。</p> + </td> + </tr> + <tr> + <td><code>form</code></td> + <td></td> + <td> + <p>小部件与之相关联的表单元素。属性值必需是同个文档中的{{HTMLElement("form")}} 元素的 <code>id</code>属性。理论上,它允许您在{{HTMLElement("form")}}元素之外设置一个表单小部件。然而,在实践中,没有任何支持该特性的浏览器。</p> + </td> + </tr> + <tr> + <td><code>name</code></td> + <td></td> + <td>元素的名称;这是跟表单数据一起提交的。</td> + </tr> + <tr> + <td><code>value</code></td> + <td></td> + <td>元素的初始值。</td> + </tr> + </tbody> +</table> + +<h2 id="文本输入框">文本输入框</h2> + +<p>文本输入框 {{htmlelement("input")}} 是最基本的表单小部件。 这是一种非常方便的方式,可以让用户输入任何类型的数据。但是,一些文本字段可以专门用于满足特定的需求。我们已经看到了几个简单的例子。</p> + +<div class="note"> +<p><strong>注意</strong>: HTML表单文本字段是简单的纯文本输入控件。 这意味着您不能使用它们执行<a href="https://developer.mozilla.org/en-US/docs/Rich-Text_Editing_in_Mozilla">富文本编辑</a>(粗体、斜体等)。你遇到的所有富文本编辑器(rich text editors)都是使用HTML、CSS和JavaScript所创建的自定义小部件。</p> +</div> + +<p>所有文本框都有一些通用规范:</p> + +<ul> + <li>它们可以被标记为 {{htmlattrxref("readonly","input")}} (用户不能修改输入值)甚至是 {{htmlattrxref("disabled","input")}} (输入值永远不会与表单数据的其余部分一起发送)。</li> + <li>它们可以有一个 {{htmlattrxref("placeholder","input")}}; 这是文本输入框中出现的文本,用来简略描述输入框的目的。</li> + <li>它们可以被限制在{{htmlattrxref("size","input")}} (框的物理尺寸) 和 {{htmlattrxref("maxlength","input")}} (可以输入的最大字符数)。</li> + <li>如果浏览器支持的话,他们可以从<a href="/en-US/docs/HTML/Element/input#attr-spellcheck">拼写检查</a>中获益。</li> +</ul> + +<div class="note"> +<p><strong>注意:</strong> {{htmlelement("input")}}元素是如此特别因为它几乎可以是任何东西。通过简单设置 <code>type</code> 属性,它可以彻底的改变,它用于创建大多数类型的表单小部件,包括单行文本字段、没有文本输入的控件、时间和日期控件和按钮。 然而,也有一些例外,比如用来多行输入的 {{htmlelement("textarea")}}。阅读这篇文章时,要注意这些。</p> +</div> + +<h3 id="单行文本框">单行文本框</h3> + +<p>使用{{htmlattrxref("type","input")}}属性值被设置为<code>text</code> 的{{HTMLElement("input")}}元素创建一个单行文本框(同样的,如果你不提供{{htmlattrxref("type","input")}}属性,<code>text</code> 是默认值)。在你指定的{{htmlattrxref("type","input")}}属性的值在浏览器中是未知的情况下(比如你指定 <code>type="date"</code>,但是浏览器不支持原生日期选择器),属性值<code>text</code>也是备用值。</p> + +<div class="note"> +<p><strong>注意:</strong> 你可以在Github上的 <a href="https://github.com/mdn/learning-area/blob/master/html/forms/native-form-widgets/single-line-text-fields.html">single-line-text-fields.html</a>找到所有单行文本框类型。(你也可以直接看<a href="https://mdn.github.io/learning-area/html/forms/native-form-widgets/single-line-text-fields.html">预览版</a>)。</p> +</div> + +<p>这是一个基本的单行文本框示例:</p> + +<pre class="brush: html notranslate"><input type="text" id="comment" name="comment" value="I'm a text field"></pre> + +<p>单行文本框只有一个真正的约束:如果您输入带有换行符的文本,浏览器会在发送数据之前删除这些换行符。</p> + +<p><img alt="Screenshots of single line text fields on several platforms." src="/files/4273/all-single-line-text-field.png" style="height: 235px; width: 655px;"></p> + +<p>HTML5通过为{{htmlattrxref("type","input")}}属性增加特殊值增强了基本单行文本框。这些值仍然将{{HTMLElement("input")}}元素转换为单行文本框,但它们为字段添加了一些额外的约束和特性。</p> + +<h4 id="E-mail_地址框">E-mail 地址框</h4> + +<p>该类型的框将 {{htmlattrxref("type","input")}}属性设置为 <code>email</code> 值:</p> + +<pre class="brush: html notranslate"><input type="email" id="email" name="email" multiple></pre> + +<p>当使用 <code>type</code>时, 用户需要在框中输入有效的电子邮件地址;任何其他内容都会导致浏览器在提交表单时显示错误。注意,这是客户端错误验证,由浏览器执行:</p> + +<p><img alt="An invalid email input showing the message Please enter an email address." src="https://mdn.mozillademos.org/files/14781/email-invalid.png" style="border-style: solid; border-width: 1px; display: block; margin: 0px auto;"></p> + +<p>通过包括{{htmlattrxref("multiple","input")}}属性,它还可以让用户将多个电子邮件地址输入相同的输入(以逗号分隔)。</p> + +<p>在一些设备上(特别是在移动设备上),可能会出现一个不同的虚拟键盘,更适合输入电子邮件地址。</p> + +<div class="note"> +<p><strong>注意</strong>: 您可以在<a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Form_validation">表单数据验证</a>文中找到关于表单验证的更多信息。</p> +</div> + +<h4 id="密码框">密码框</h4> + +<p>通过设置{{htmlattrxref("type","input")}} 属性值为<code>password</code>来设置该类型框:</p> + +<pre class="brush: html notranslate"><input type="password" id="pwd" name="pwd"></pre> + +<p>它不会为输入的文本添加任何特殊的约束,但是它会模糊输入到字段中的值(例如,用点或小行星),这样它就不能被其他人读取。</p> + +<p>请记住,这只是一个用户界面特性;除非你安全地提交你的表单,否则它会以明文发送,这不利于安全——恶意的一方可能会截获你的数据,窃取你的密码、信用卡信息,或者你提交的其他任何东西。保护用户不受此影响的最佳方式是在安全连接上托管任何涉及表单的页面(例如:https://……地址),使得数据在发送之前就已加密。</p> + +<p>现代浏览器认识到在不安全的连接上发送表单数据所带来的安全影响,并且已经实现了警告,以阻止用户使用不安全的表单。有关Firefox实现的更多信息,请参见<a href="/en-US/docs/Web/Security/Insecure_passwords">不安全的密码</a>。</p> + +<h4 id="搜索框">搜索框</h4> + +<p>通过设置 {{htmlattrxref("type","input")}}属性值为 <code>search</code> 来设置该类型框:</p> + +<pre class="brush: html notranslate"><input type="search" id="search" name="search"></pre> + +<p>文本框和搜索框之间的主要区别是浏览器的样式——通常,搜索框是渲染成圆角的,并且/可能给定一个“x”来清除输入的值。然而,还有另外一个值得注意的特性:它们的值可以被自动保存用来在同一站点上的多个页面上自动补全。</p> + +<p><img alt="Screenshots of search fields on several platforms." src="/files/4269/all-search-field.png" style="height: 235px; width: 655px;"></p> + +<h4 id="电话号码栏:">电话号码栏:</h4> + +<p>通过 {{htmlattrxref("type","input")}}属性的 <code>tel</code> 值设置该类型框:</p> + +<pre class="brush: html notranslate"><input type="tel" id="tel" name="tel"></pre> + +<p>由于世界范围内各种各样的电话号码格式,这种类型的字段不会对用户输入的值执行任何限制(包括字母,等等)。这主要是在语义上的区分,尽管在一些设备上(特别是在移动设备上),可能会出现一个不同的虚拟键盘,更适合输入电话号码。</p> + +<h4 id="URL_栏">URL 栏</h4> + +<p>通过{{htmlattrxref("type","input")}}属性的<code>url</code> 值设置该类型框:</p> + +<pre class="brush: html notranslate"><input type="url" id="url" name="url"></pre> + +<p>它为字段添加了特殊的验证约束,如果输入无效的url,浏览器就会报告错误。</p> + +<div class="note"><strong>注意:</strong>URL格式良好并不一定意味着它引用了一个实际存在的位置。</div> + +<div class="note"> +<p><strong>注意:</strong>有特殊约束并出错了的输入框可以防止表单被发送;此外,还可以将它们设置为使错误更清晰。我们将在<a href="/en-US/docs/HTML/Forms/Data_form_validation">数据表单验证</a>中详细讨论这个问题。</p> +</div> + +<h3 id="多行文本框">多行文本框</h3> + +<p>多行文本框专指使用 {{HTMLElement("textarea")}}元素,而不是使用{{HTMLElement("input")}} 元素。</p> + +<pre class="brush: html notranslate"><textarea cols="30" rows="10"></textarea></pre> + +<p>textarea和常规的单行文本字段之间的主要区别是,允许用户输入包含硬换行符(即按回车)的文本。</p> + +<p><img alt="Screenshots of multi-lines text fields on several platforms." src="/files/4271/all-multi-lines-text-field.png" style="height: 330px; width: 745px;"></p> + +<div class="note"> +<p><strong>注意:</strong>你可以在Github上的<a href="https://github.com/mdn/learning-area/blob/master/html/forms/native-form-widgets/multi-line-text-field.html">multi-line-text-field.html</a>看到本例(你也可以看<a href="https://mdn.github.io/learning-area/html/forms/native-form-widgets/multi-line-text-field.html">预览版</a>)。注意到在大多数浏览器中,文本区域在右下角有一个拖放操作,允许用户调整它的大小。这种调整能力可以通过使用<a href="/en-US/docs/Learn/CSS">CSS</a>设置文本区域的{{cssxref("resize")}}性质为 <code>none</code> 来关闭。</p> +</div> + +<p>{{htmlelement("textarea")}} 还接受了一些额外的属性,以控制它在几行代码中呈现的效果 (除此以外还有其他几个):</p> + +<p><strong style="font-style: inherit; font-weight: 700;">{{HTMLElement("textarea")}} 元素属性</strong></p> + +<table> + <thead> + <tr> + <th scope="col">属性名</th> + <th scope="col">默认值</th> + <th scope="col">描述</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{htmlattrxref("cols","textarea")}}</td> + <td><code>20</code></td> + <td>文本控件的可见宽度,平均字符宽度。</td> + </tr> + <tr> + <td>{{htmlattrxref("rows","textarea")}}</td> + <td></td> + <td>控制的可见文本行数。</td> + </tr> + <tr> + <td>{{htmlattrxref("wrap","textarea")}}</td> + <td><code>soft</code></td> + <td>表示控件是如何包装文本的。可能的值:<code>hard</code> 或 <code>soft</code></td> + </tr> + </tbody> +</table> + +<p>注意,{{HTMLElement("textarea")}}元素与{{HTMLElement("input")}}元素的编写略有不同。{{HTMLElement("input")}}元素是一个空元素,这意味着它不能包含任何子元素。另一方面,{{HTMLElement("textarea")}}元素是一个常规元素,可以包含文本内容的子元素。</p> + +<p>这里有两个关键点需要注意:</p> + +<ul> + <li>如果您想为{{HTMLElement("input")}}元素定义一个默认值,那么您必须使用<code>value</code>属性;另一方面,对于{{HTMLElement("textarea")}}元素,只需要将默认的文本放在起始标记和{{HTMLElement("textarea")}}的结束标记之间。</li> + <li>因为它的本质, {{HTMLElement("textarea")}}元素只接受文本内容;这意味着将任何HTML内容放入{{HTMLElement("textarea")}}中都呈现为纯文本内容。</li> +</ul> + +<h2 id="下拉内容">下拉内容</h2> + +<p>下拉窗口小部件是一种简单的方法,可以让用户选择众多选项中的一个,而不需要占用用户界面的太多空间。HTML有两种类型的下拉内容:<strong>select box</strong>和<strong>autocomplete box</strong>。在这两种情况下,交互都是相同的——一旦控件被激活,浏览器就会显示用户可以选择的值列表。</p> + +<div class="note"> +<p><strong>注意:</strong>你可以在Github上的<a href="https://github.com/mdn/learning-area/blob/master/html/forms/native-form-widgets/drop-down-content.html">drop-down-content.html</a>看到本例(你也可以看<a href="https://mdn.github.io/learning-area/html/forms/native-form-widgets/drop-down-content.html">预览版</a>)。</p> +</div> + +<h3 id="选择框">选择框</h3> + +<p>一个选择框是用{{HTMLElement("select")}}元素创建的,其中有一个或多个{{HTMLElement("option")}}元素作为子元素,每个元素都指定了其中一个可能的值。</p> + +<pre class="brush: html notranslate"><select id="simple" name="simple"> + <option>Banana</option> + <option>Cherry</option> + <option>Lemon</option> +</select></pre> + +<p>如果需要,可以使用{{htmlattrxref("selected","option")}}属性在所需的{{HTMLElement("option")}}元素上设置选择框的默认值---在页面加载时会默认选择该选项。{{HTMLElement("option")}}元素也可以嵌套在{{HTMLElement("optgroup")}}元素中,以创建视觉关联的组值:</p> + +<pre class="brush: html notranslate"><select id="groups" name="groups"> + <optgroup label="fruits"> + <option>Banana</option> + <option selected>Cherry</option> + <option>Lemon</option> + </optgroup> + <optgroup label="vegetables"> + <option>Carrot</option> + <option>Eggplant</option> + <option>Potato</option> + </optgroup> +</select></pre> + +<p><img alt="Screenshots of single line select box on several platforms." src="/files/4517/all-select.png" style="height: 636px; width: 887px;"></p> + +<p>如果一个{{HTMLElement("option")}}元素设置了<code>value</code>属性,那么当提交表单时该属性的值就会被发送。如果忽略了<code>value</code>属性,则使用{{HTMLElement("option")}}元素的内容作为选择框的值。</p> + +<p>在{{HTMLElement("optgroup")}}元素中,<code>label</code>属性显示在值之前,但即使它看起来有点像一个选项,它也不是可选的。</p> + +<h3 id="多选选择框">多选选择框</h3> + +<p>默认情况下,选择框只允许用户选择一个值。通过将{{htmlattrxref("multiple","select")}}属性添加到{{HTMLElement("select")}}元素,您可以允许用户通过操作系统提供的默认机制来选择几个值。 (如, 同时按下 <kbd>Cmd</kbd>/<kbd>Ctrl</kbd> 并点击多个值).</p> + +<p>注意:在多个选项选择框的情况下,选择框不再显示值为下拉内容——相反,它们都显示在一个列表中。</p> + +<pre class="brush: html notranslate"><select multiple id="multi" name="multi"> + <option>Banana</option> + <option>Cherry</option> + <option>Lemon</option> +</select></pre> + +<p><img alt="Screenshots of multi-lines select box on several platforms." src="/files/4559/all-multi-lines-select.png" style="height: 531px; width: 734px;"></p> + +<div class="note"><strong>注意:</strong>所有支持 {{HTMLElement("select")}} 元素的浏览器也支持 {{htmlattrxref("multiple","select")}} 。</div> + +<h3 id="自动补全输入框">自动补全输入框</h3> + +<p>您可以使用{{HTMLElement("datalist")}}元素来为表单小部件提供建议的、自动完成的值,并使用一些{{HTMLElement("option")}}子元素来指定要显示的值。</p> + +<p>然后使用{{htmlattrxref("list","input")}}属性将数据列表绑定到一个文本框(通常是一个 <code><input></code> 元素)。</p> + +<p>一旦数据列表与表单小部件相关联,它的选项用于自动完成用户输入的文本;通常,这是作为一个下拉框提供给用户的,匹配在输入框中输入了的内容。</p> + +<pre class="brush: html notranslate"><label for="myFruit">What's your favorite fruit?</label> +<input type="text" name="myFruit" id="myFruit" list="mySuggestion"> +<datalist id="mySuggestion"> + <option>Apple</option> + <option>Banana</option> + <option>Blackberry</option> + <option>Blueberry</option> + <option>Lemon</option> + <option>Lychee</option> + <option>Peach</option> + <option>Pear</option> +</datalist></pre> + +<div class="note"><strong>注意:</strong> 根据<a href="http://www.w3.org/TR/html5/common-input-element-attributes.html#attr-input-list">HTML规范</a>,{{htmlattrxref("list","input")}} 属性和{{HTMLElement("datalist")}}元素元素可以用于任何需要用户输入的小部件。但是,除了文本控件外(例如颜色或日期),还不清楚它会如何工作,不同的浏览器在不同的情况下会有不同的表现。正因为如此,除了文本字段以外,要小心使用这个特性。</div> + +<div><img alt="Screenshots of datalist on several platforms." src="/files/4593/all-datalist.png" style="height: 329px; width: 437px;"></div> + +<div></div> + +<h4 id="数据列表支持和后备">数据列表支持和后备</h4> + +<p>{{HTMLElement("datalist")}}元素是HTML表单的最新补充,因此浏览器的支持比我们之前看到的要少一些。最值得注意的是,它在版本小于10的IE中不受支持,同时在版本小于12的Safari中不受支持。</p> + +<p>为了处理这个问题,这里有一个小技巧,可以为这些浏览器提供一个不错的备用:</p> + +<pre class="brush:html; notranslate"><label for="myFruit">What is your favorite fruit? (With fallback)</label> +<input type="text" id="myFruit" name="fruit" list="fruitList"> + +<datalist id="fruitList"> + <label for="suggestion">or pick a fruit</label> + <select id="suggestion" name="altFruit"> + <option>Apple</option> + <option>Banana</option> + <option>Blackberry</option> + <option>Blueberry</option> + <option>Lemon</option> + <option>Lychee</option> + <option>Peach</option> + <option>Pear</option> + </select> +</datalist> +</pre> + +<p>支持{{HTMLElement("datalist")}}元素的浏览器将忽略所有不是{{HTMLElement("option")}}元素的元素,并按照预期工作。另一方面,不支持{{HTMLElement("datalist")}}元素的浏览器将显示标签和选择框。当然,还有其他方法可以处理对{{HTMLElement("datalist")}}元素支持的不足,但这是最简单的(其他方法往往需要JavaScript)。</p> + +<table> + <tbody> + <tr> + <th scope="row">Safari 6</th> + <td><img alt="Screenshot of the datalist element fallback with Safari on Mac OS" src="/files/4583/datalist-safari.png" style="height: 32px; width: 495px;"></td> + </tr> + <tr> + <th scope="row">Firefox 18</th> + <td><img alt="Screenshot of the datalist element with Firefox on Mac OS" src="/files/4581/datalist-firefox-macos.png" style="height: 102px; width: 353px;"></td> + </tr> + </tbody> +</table> + +<h2 id="可选中项">可选中项</h2> + +<p>可选中项是可以通过单击它们来更改状态的小部件。有两种可选中项:复选框和单选按钮。两者都使用{{htmlattrxref("checked","input")}}属性,以指示该部件的默认状态: "选中"或"未选中"。</p> + +<p>值得注意的是,这些小部件与其他表单小部件不一样。对于大多数表单部件,一旦表单提交,所有具有{{htmlattrxref("name","input")}}属性的小部件都会被发送,即使没有任何值被填。对于可选中项,只有在勾选时才发送它们的值。如果他们没有被勾选,就不会发送任何东西,甚至连他们的名字也没有。</p> + +<div class="note"> +<p><strong>注意</strong>: 你可以在Github上看到 <a href="https://github.com/mdn/learning-area/blob/master/html/forms/native-form-widgets/checkable-items.html">checkable-items.html</a> (你也可以看<a href="https://mdn.github.io/learning-area/html/forms/native-form-widgets/checkable-items.html">预览版</a>)。</p> +</div> + +<p>为了获得最大的可用性和可访问性,建议您在{{htmlelement("fieldset")}}中包围每个相关项目的列表,并使用{{htmlelement("legend")}}提供对列表的全面描述。每个单独的{{htmlelement("label")}}/{{htmlelement("input")}}元素都应该包含在它自己的列表项中(或者类似的)。正如在示例中显示的。</p> + +<p>您还需要为这些类型的输入提供<code>value</code>属性,如果您想让它们具有意义——如果没有提供任何值,则复选框和单选按钮被赋予一个 <code>on</code>值。</p> + +<h3 id="复选框">复选框</h3> + +<p>使用{{htmlattrxref("type","input")}}属性值为<code>checkbox</code>的 {{HTMLElement("input")}}元素来创建一个复选框。</p> + +<pre class="brush: html notranslate"><input type="checkbox" checked id="carrots" name="carrots" value="carrots"> +</pre> + +<p>包含<code>checked</code>属性使复选框在页面加载时自动被选中。</p> + +<p><img alt="Screenshots of check boxes on several platforms." src="/files/4595/all-checkbox.png" style="height: 198px; width: 352px;"></p> + +<h3 id="单选按钮">单选按钮</h3> + +<p>使用{{htmlattrxref("type","input")}}属性值为<code>radio</code>的 {{HTMLElement("input")}}元素来创建一个单选按钮。</p> + +<pre class="brush: html notranslate"><input type="radio" checked id="soup" name="meal"></pre> + +<p>几个单选按钮可以连接在一起。如果它们的{{htmlattrxref("name","input")}}属性共享相同的值,那么它们将被认为属于同一组的按钮。同一组中只有一个按钮可以同时被选;这意味着当其中一个被选中时,所有其他的都将自动未选中。如果没有选中任何一个,那么整个单选按钮池就被认为处于未知状态,并且没有以表单的形式发送任何值。</p> + +<pre class="brush: html notranslate"><fieldset> + <legend>What is your favorite meal?</legend> + <ul> + <li> + <label for="soup">Soup</label> + <input type="radio" checked id="soup" name="meal" value="soup"> + </li> + <li> + <label for="curry">Curry</label> + <input type="radio" id="curry" name="meal" value="curry"> + </li> + <li> + <label for="pizza">Pizza</label> + <input type="radio" id="pizza" name="meal" value="pizza"> + </li> + </ul> +</fieldset></pre> + +<p><img alt="Screenshots of radio buttons on several platforms." src="/files/4597/all-radio.png" style="height: 198px; width: 352px;"></p> + +<h2 id="按钮">按钮</h2> + +<p>在HTML表单中,有三种按钮:</p> + +<dl> + <dt>Submit</dt> + <dd>将表单数据发送到服务器。对于{{HTMLElement("button")}} 元素, 省略 <code>type</code> 属性 (或是一个无效的 <code>type</code> 值) 的结果就是一个提交按钮.</dd> + <dt>Reset</dt> + <dd>将所有表单小部件重新设置为它们的默认值。</dd> + <dt>Anonymous</dt> + <dd>没有自动生效的按钮,但是可以使用JavaScript代码进行定制。</dd> +</dl> + +<div class="note"> +<p><strong>注意</strong>: 你可以在Github上看到<a href="https://github.com/mdn/learning-area/blob/master/html/forms/native-form-widgets/button-examples.html">button-examples.html</a> (你也可以看<a href="https://mdn.github.io/learning-area/html/forms/native-form-widgets/button-examples.html">预览版</a>)。</p> +</div> + +<p>使用 {{HTMLElement("button")}}元素或者{{HTMLElement("input")}}元素来创建一个按钮。{{htmlattrxref("type","input")}}属性的值指定显示什么类型的按钮。</p> + +<h3 id="submit">submit</h3> + +<pre class="brush: html notranslate"><button type="submit"> + This a <br><strong>submit button</strong> +</button> + +<input type="submit" value="This is a submit button"></pre> + +<h3 id="reset">reset</h3> + +<pre class="brush: html notranslate"><button type="reset"> + This a <br><strong>reset button</strong> +</button> + +<input type="reset" value="This is a reset button"></pre> + +<h3 id="button">button</h3> + +<pre class="brush: html notranslate"><button type="button"> + This an <br><strong>anonymous button</strong> +</button> + +<input type="button" value="This is an anonymous button"></pre> + +<p>不管您使用的是{{HTMLElement("button")}}元素还是{{HTMLElement("input")}}元素,按钮的行为都是一样的。然而,有一些显著的不同之处:</p> + +<ul> + <li>从示例中可以看到,{{HTMLElement("button")}}元素允许您在它们的标签中使用HTML内容,这些内容被插入到打开和关闭<code><button></code> 标签中。另一方面,{{HTMLElement("input")}}元素是空元素;它们的标签插入在<code>value</code>属性中,因此只接受纯文本内容。</li> + <li>使用{{HTMLElement("button")}}元素,可以有一个不同于按钮标签的值(通过设置<code>value</code>中的属性值)。这在IE 8之前的版本中是不可靠的。</li> +</ul> + +<p><img alt="Screenshots of buttons on several platforms." src="/files/4599/all-buttons.png" style="height: 235px; width: 464px;"></p> + +<p>从技术上讲,使用{{HTMLElement("button")}}元素或{{HTMLElement("input")}}元素定义的按钮几乎没有区别。唯一值得注意的区别是按钮本身的标签。在{{HTMLElement("input")}}元素中,标签只能是字符数据,而在{{HTMLElement("button")}}元素中,标签可以是HTML,因此可以相应地进行样式化。</p> + +<h2 id="高级表单部件">高级表单部件</h2> + +<p>在本节中,我们将介绍那些让用户输入复杂或不寻常数据的小部件。这包括精确的或近似的数字,日期和时间,或颜色。</p> + +<div class="note"> +<p><strong>注意</strong>: 你可以在Github上看到<a href="https://github.com/mdn/learning-area/blob/master/html/forms/native-form-widgets/advanced-examples.html">advanced-examples.html</a> (你也可以看<a href="https://mdn.github.io/learning-area/html/forms/native-form-widgets/advanced-examples.html">预览版</a>)。</p> +</div> + +<h3 id="数字">数字</h3> + +<p>用于数字的小部件是用{{htmlattrxref("type","input")}}属性设置为<code>number</code>{{HTMLElement("input")}}的元素创建的。这个控件看起来像一个文本框,但是只允许浮点数,并且通常提供一些按钮来增加或减少小部件的值。</p> + +<p>也可以:</p> + +<ul> + <li>通过设置{{htmlattrxref("min","input")}}和{{htmlattrxref("max","input")}}属性来约束该值。</li> + <li>通过设置{{htmlattrxref("step","input")}}属性来指定增加和减少按钮更改小部件的步进值大小。</li> +</ul> + +<h4 id="例子">例子</h4> + +<pre class="brush: html notranslate"><input type="number" name="age" id="age" min="1" max="10" step="2"></pre> + +<p>这将创建一个数字小部件,其值被限制为1到10之间的任何值,而其增加和减少按钮的步进值将更改为2。</p> + +<p>在10以下的Internet Explorer版本中不支持<code>number</code> 输入。</p> + +<h3 id="滑块">滑块</h3> + +<p>另一种选择数字的方法是使用滑块。从视觉上讲,滑块没有文本字段准确,因此它们被用来选择一个确切值并不重要的数字。</p> + +<p>滑块是通过把{{HTMLElement("input")}}元素的{{htmlattrxref("type","input")}}属性值设置为<code>range</code>来创建的。正确配置滑块是很重要的;为了达到这个目的,我们强烈建议您设置{{htmlattrxref("min","input")}}、{{htmlattrxref("max","input")}}和{{htmlattrxref("step","input")}}属性。</p> + +<h4 id="例子_2">例子</h4> + +<pre class="brush: html notranslate"><input type="range" name="beans" id="beans" min="0" max="500" step="10"></pre> + +<p>这个例子创建了一个滑块,它可能的值在0到500之间,而它的递增/递减按钮以+10和-10来改变值。</p> + +<p>滑块的一个问题是,它们不提供任何形式的视觉反馈,以了解当前的值是什么。您需要使用JavaScript来添加这一点,但这相对来说比较容易。在本例中,我们添加了一个空的{{htmlelement("span")}}元素,其中我们将写入滑块的当前值,并随着更改实时更新它。</p> + +<pre class="brush: html notranslate"><label for="beans">How many beans can you eat?</label> +<input type="range" name="beans" id="beans" min="0" max="500" step="10"> +<span class="beancount"></span></pre> + +<p>可以使用一些简单的JavaScript实现</p> + +<pre class="brush: js notranslate">var beans = document.querySelector('#beans'); +var count = document.querySelector('.beancount'); + +count.textContent = beans.value; + +beans.oninput = function() { + count.textContent = beans.value; +}</pre> + +<p>这里我们将对范围输入值和span的引用存储在两个变量里,然后我们立即将span的<code><a href="/en-US/docs/Web/API/Node/textContent">textContent</a></code>设置为输入的当前<code>value</code>。最后,我们设置了一个<code>oninput</code>事件处理程序,以便每次移动范围滑块时,都会将span <code>textContent</code>更新为新的输入值。</p> + +<p>在10以下的Internet Explorer版本中不支持<code>range</code> 。</p> + +<h3 id="日期时间选择器">日期时间选择器</h3> + +<p>对于web开发人员来说,收集日期和时间值一直是一场噩梦。HTML5通过提供一种特殊的控制来处理这种特殊的数据,从而带来了一些增强。</p> + +<p>使用{{HTMLElement("input")}}元素和一个适当的值的{{htmlattrxref("type","input")}}属性来创建日期和时间控制,这取决于您是否希望收集日期、时间或两者都。</p> + +<h4 id="本地时间"><code>本地时间</code></h4> + +<p>这将创建一个小部件来显示和选择一个日期,但是没有任何特定的时区信息。</p> + +<pre class="brush: html notranslate"><input type="datetime-local" name="datetime" id="datetime"></pre> + +<h4 id="月"><code>月</code></h4> + +<p>这就创建了一个小部件来显示和挑选一个月。</p> + +<pre class="brush: html notranslate"><input type="month" name="month" id="month"></pre> + +<h4 id="时间"><font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: #eeeeee;">时间</span></font></h4> + +<p>这将创建一个小部件来显示并选择一个时间值。</p> + +<pre class="brush: html notranslate"><input type="time" name="time" id="time"></pre> + +<h4 id="星期"><code>星期</code></h4> + +<p>这将创建一个小部件来显示并挑选一个星期号和它的年份。</p> + +<pre class="brush: html notranslate"><input type="week" name="week" id="week"></pre> + +<p>所有日期和时间控制都可以使用{{htmlattrxref("min","input")}}和{{htmlattrxref("max","input")}}属性来约束。</p> + +<pre class="brush: html notranslate"><label for="myDate">When are you available this summer?</label> +<input type="date" name="myDate" min="2013-06-01" max="2013-08-31" id="myDate"></pre> + +<p>警告——日期和时间窗口小部件仍然很不受支持。目前,Chrome、Edge和Opera都支持它们,但IE浏览器没有支持,Firefox和Safari对这些都没有太大的支持。</p> + +<h3 id="拾色器">拾色器</h3> + +<p>颜色总是有点难处理。有很多方式来表达它们:RGB值(十进制或十六进制)、HSL值、关键字等等。颜色小部件允许用户在文本和可视的方式中选择颜色。</p> + +<p>一个颜色小部件是使用{{htmlattrxref("type","input")}}属性设置为值<code>color</code>{{HTMLElement("input")}}的元素创建的。</p> + +<pre class="brush: html notranslate"><input type="color" name="color" id="color"></pre> + +<p>警告——并不是所有浏览器都支持拾色器。IE中没有支持,Safari目前也不支持它。其他主要的浏览器都支持它。</p> + +<h2 id="其他小部件">其他小部件</h2> + +<p>还有一些其他的小部件由于它们非常特殊的行为而不能很容易地分类,但是它们仍然非常有用。</p> + +<div class="note"> +<p><strong>注意</strong>: 你可以在Github上看到<a href="https://github.com/mdn/learning-area/blob/master/html/forms/native-form-widgets/other-examples.html">other-examples.html</a>(你也可以看<a href="https://mdn.github.io/learning-area/html/forms/native-form-widgets/other-examples.html">预览版</a>)。</p> +</div> + +<h3 id="文件选择器">文件选择器</h3> + +<p>HTML表单能够将文件发送到服务器;在<a href="/en-US/docs/Learn/HTML/Forms/Sending_and_retrieving_form_data">发送和检索表单数据</a>的文章中详细描述了这个特定的操作。文件选择器小部件是用户如何选择一个或多个文件来发送的。</p> + +<p>要创建一个文件选择器小部件,您可以使用{{HTMLElement("input")}}元素,将它的{{htmlattrxref("type","input")}}属性设置为<code>file</code>。被接受的文件类型可以使用{{htmlattrxref("accept","input")}}属性来约束。此外,如果您想让用户选择多个文件,那么可以通过添加{{htmlattrxref("multiple","input")}}属性来实现。</p> + +<h4 id="例子_3">例子</h4> + +<p>在本例中,创建一个文件选择器,请求图形图像文件。在本例中,允许用户选择多个文件。</p> + +<pre class="brush: html notranslate"><input type="file" name="file" id="file" accept="image/*" multiple></pre> + +<h3 id="隐藏内容">隐藏内容</h3> + +<p>有时候,由于为了方便技术原因,有些数据是用表单发送的,但不显示给用户。要做到这一点,您可以在表单中添加一个不可见的元素。要做到这一点,需要使用{{HTMLElement("input")}}将它的{{htmlattrxref("type","input")}}属性设置为<code>hidden</code>值。</p> + +<p>如果您创建了这样一个元素,就需要设置它的<code>name</code>和<code>value</code>属性:</p> + +<pre class="brush: html notranslate"><input type="hidden" id="timestamp" name="timestamp" value="1286705410"></pre> + +<h3 id="图像按钮">图像按钮</h3> + +<p>图像按钮控件是一个与{{HTMLElement("img")}}元素完全相同的元素,除了当用户点击它时,它的行为就像一个提交按钮(见上面)。</p> + +<p>图像按钮是使用{{htmlattrxref("type","input")}}属性值设置为<code>image</code>{{HTMLElement("input")}}的元素创建的。这个元素支持与{{HTMLElement("img")}}元素相同的属性,和其他表单按钮支持的所有属性。</p> + +<pre class="brush: html notranslate"><input type="image" alt="Click me!" src="my-img.png" width="80" height="30" /></pre> + +<p>如果使用图像按钮来提交表单,这个小部件不会提交它的值;相反,提交的是在图像上单击处的X和Y坐标(坐标是相对于图像的,这意味着图像的左上角表示坐标0,0),坐标被发送为两个键/值对:</p> + +<ul> + <li>X值键是{{htmlattrxref("name","input")}}属性的值,后面是字符串“.x”。</li> + <li>Y值键是{{htmlattrxref("name","input")}}属性的值,后面是字符串“.y”。</li> +</ul> + +<p>例如,当您点击这个小部件的图像时,您将被发送到一个URL,如下所显示的</p> + +<pre class="notranslate">http://foo.com?pos.x=123&pos.y=456</pre> + +<p>这是构建“热图”的一种非常方便的方式。如何发送和检索这些值在<a href="/en-US/docs/Learn/HTML/Forms/Sending_and_retrieving_form_data">发送和检索表单数据</a>文章中详细说明。</p> + +<h3 id="仪表和进度条">仪表和进度条</h3> + +<p>仪表和进度条是数值的可视化表示。</p> + +<h4 id="进度条">进度条</h4> + +<p>一个进度条表示一个值,它会随着时间的变化而变化到最大的值,这个值由{{htmlattrxref("max","progress")}}属性指定。这样的一个bar是使用{{ HTMLElement("progress")}}元素创建的。</p> + +<pre class="brush: html notranslate"><progress max="100" value="75">75/100</progress></pre> + +<p>这是为了实现任何需要进度报告的内容,例如下载的总文件的百分比,或者问卷中填写的问题的数量。</p> + +<p>{{HTMLElement("progress")}}元素中的内容用于不支持该元素的浏览器的回退,以及辅助技术对其朗读。</p> + +<h4 id="仪表">仪表</h4> + +<p>一个仪表表示一个固定值,这个值由一个{{htmlattrxref("min","meter")}}和一个{{htmlattrxref("max","meter")}}值所界定。这个值是作为一个条形显示的,并且为了知道这个工具条是什么样子的,我们将这个值与其他一些设置值进行比较</p> + +<ul> + <li> {{htmlattrxref("low","meter")}} 和 {{htmlattrxref("high","meter")}} 值范围划分为三个部分: + <ul> + <li>该范围的较低部分是在{{htmlattrxref("min","meter")}}和{{htmlattrxref("low","meter")}}值(包括那些值)之间。</li> + <li>该范围的中间部分是在{{htmlattrxref("low","meter")}}和{{htmlattrxref("high","meter")}}值之间(不包括那些值)。</li> + <li>该范围的较高部分是在{{htmlattrxref("high","meter")}}和{{htmlattrxref("max","meter")}}值(包括那些值)之间。</li> + </ul> + </li> + <li>{{htmlattrxref("optimum","meter")}}值定义了{{HTMLElement("meter")}}元素的最优值。在与htmlattrxref(“low”、“meter”)和{{htmlattrxref("high","meter")}}值的联合中,它定义了该范围的哪个部分是优先的: + <ul> + <li>如果{{htmlattrxref("optimum","meter")}}值在较低的范围内,则较低的范围被认为是首选项,中等范围被认为是一般的,而较高的范围被认为是最坏的部分。</li> + <li>如果{{htmlattrxref("optimum","meter")}}值在该范围的中等部分,则较低的范围被认为是一个一般的,中等范围被认为是优先的部分,而较高的范围也被认为是平均值。</li> + <li>如果{{htmlattrxref("optimum","meter")}}值在较高的范围内,则较低的范围被认为是最坏的部分,中等范围被认为是一般的部分,较高的范围被认为是优先的部分。</li> + </ul> + </li> +</ul> + +<p>所有实现{{HTMLElement("meter")}}元素的浏览器都使用这些值来改变米尺的颜色。</p> + +<ul> + <li>如果当前值位于该范围的优先部分,则该条是绿色的。</li> + <li>如果当前值位于该范围的平均部分,则该条是黄色的。</li> + <li>如果当前值处于最糟糕的范围,则该条是红色的。</li> +</ul> + +<p>这样的一个工具栏是使用{{HTMLElement("meter")}}元素创建的。这是用于实现任何类型的仪表,例如一个显示磁盘上使用的总空间的条,当它开始满时,它会变成红色。</p> + +<pre class="brush: html notranslate"><meter min="0" max="100" value="75" low="33" high="66" optimum="50">75</meter></pre> + +<p>{{HTMLElement("meter")}}元素中的内容是不支持该元素的浏览器的回退,以及辅助技术对其发出的声音。</p> + +<p>对进度条和仪表的支持是相当不错的,在Internet Explorer中没有支持,但是其他浏览器都可以很好的支持它。</p> + +<h2 id="总结">总结</h2> + +<p>正如您在上面看到的,有许多不同类型的可用表单元素——您不需要一次性记住所有细节,可以随时返回本文查看详细信息。</p> + +<h2 id="另见">另见</h2> + +<p>要深入了解不同的表单小部件,您需要了解一些有用的外部资源:</p> + +<ul> + <li><a href="http://wufoo.com/html5/" rel="external" title="http://wufoo.com/html5/">The Current State of HTML5 Forms</a> by Wufoo</li> + <li><a href="http://www.quirksmode.org/html5/inputs.html" rel="external" title="http://www.quirksmode.org/html5/inputs.html">HTML5 Tests - inputs</a> on Quirksmode (also <a href="http://www.quirksmode.org/html5/inputs_mobile.html" rel="external" title="http://www.quirksmode.org/html5/inputs_mobile.html">available for mobile</a> browsers)</li> +</ul> + +<p>{{PreviousMenuNext("Learn/HTML/Forms/How_to_structure_an_HTML_form", "Learn/HTML/Forms/Sending_and_retrieving_form_data", "Learn/HTML/Forms")}}</p> diff --git a/files/zh-cn/learn/html/forms/your_first_html_form/index.html b/files/zh-cn/learn/html/forms/your_first_html_form/index.html new file mode 100644 index 0000000000..5b0adc1480 --- /dev/null +++ b/files/zh-cn/learn/html/forms/your_first_html_form/index.html @@ -0,0 +1,266 @@ +--- +title: 创建我的第一个表单 +slug: Learn/HTML/Forms/Your_first_HTML_form +translation_of: Learn/Forms/Your_first_form +--- +<p>{{LearnSidebar}}{{NextMenu("Learn/HTML/Forms/How_to_structure_an_HTML_form", "Learn/HTML/Forms")}}</p> + +<p class="summary">本系列的第一篇文章提供了您第一次创建HTML表单的经验,包括设计一个简单表单,使用正确的HTML元素实现它,通过CSS添加一些非常简单的样式,以及如何将数据发送到服务器。</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">预备知识:</th> + <td> + <p>基本计算机素养和<a href="/en-US/docs/Learn/HTML/Introduction_to_HTML">对HTML的基本理解</a>。</p> + </td> + </tr> + <tr> + <th scope="row">目标:</th> + <td>为了熟悉HTML表单是什么,它们被用来做什么,如何设计它们,以及简单情况下需要的基本HTML元素。</td> + </tr> + </tbody> +</table> + +<h2 id="HTML表单是什么?">HTML表单是什么?</h2> + +<p>HTML表单是用户和web站点或应用程序之间交互的主要内容之一。它们允许用户将数据发送到web站点。大多数情况下,数据被发送到web服务器,但是web页面也可以自己拦截它并使用它。</p> + +<p>HTML表单是由一个或多个小部件组成的。这些小部件可以是文本字段(单行或多行)、选择框、按钮、复选框或单选按钮。大多数情况下,这些小部件与描述其目的的标签配对——正确实现的标签能够清楚地指示视力正常的用户和盲人用户输入表单所需的内容。</p> + +<p>HTML表单和常规HTML文档的主要区别在于,大多数情况下,表单收集的数据被发送到web服务器。在这种情况下,您需要设置一个web服务器来接收和处理数据。如何设置这样的服务器超出了本文的范围,但是如果您想了解更多,请参阅模块后面的<a href="/zh-CN/docs/Learn/HTML/Forms/Sending_and_retrieving_form_data">发送表单数据</a>。</p> + +<h2 id="设计表单">设计表单</h2> + +<p>在开始编写代码之前,最好先退一步,花点时间考虑一下您的表单。设计一个快速的模型将帮助您定义您想要询问用户的正确的数据集。从用户体验(UX)的角度来看,要记住:表单越大,失去用户的风险就越大。保持简单,保持专注:只要求必要的数据。在构建站点或应用程序时,设计表单是非常重要的一步。这超出了本文的范围,涵盖了表单的用户体验,但是如果您想深入了解这个主题,您应该阅读下面的文章:</p> + +<ul> + <li>杂志<Smashing Magazine>中有<a href="http://uxdesign.smashingmagazine.com/tag/forms/">很好的关于表单用户体验的文章</a>,或许其中最重要的应该是他们的<a href="http://uxdesign.smashingmagazine.com/2011/11/08/extensive-guide-web-form-usability/" rel="external" title="http://uxdesign.smashingmagazine.com/2011/11/08/extensive-guide-web-form-usability/">Extensive Guide To Web Form Usability</a>.</li> + <li>UXMatters 也是一个非常有思想的资源,从基本的<a href="http://www.uxmatters.com/mt/archives/2012/05/7-basic-best-practices-for-buttons.php" rel="拓展" title="http://www.uxmatters.com/mt/archives/2012/05/7-basic-best-practices-for-buttons.php">最佳实践</a>到复杂的问题如<a href="https://www.uxmatters.com/mt/archives/2010/03/pagination-in-web-forms-evaluating-the-effectiveness-of-web-forms.php">多页表单</a>,都有很好的建议。</li> +</ul> + +<p>在本文中,我们将构建一个简单的联系人表单。让我们做一个粗略的草图。</p> + +<p><img alt="The form to build, roughly sketch" src="/files/4579/form-sketch-low.jpg" style="border-style: solid; border-width: 1px; height: 352px; width: 400px;"></p> + +<p>我们的表单将包含三个文本字段和一个按钮。我们向用户询问他们的姓名、电子邮件和他们想要发送的信息。点击这个按钮将把他们的数据发送到一个web服务器。</p> + +<h2 id="主动学习使用HTML实现我们的表单">主动学习:使用HTML实现我们的表单</h2> + +<p>好了,现在我们准备进入HTML代码并对表单进行编码。为了构建我们的联系人表单,我们将使用以下HTML元素:{{HTMLElement("form")}}, {{HTMLElement("label")}}, {{HTMLElement("input")}}, {{HTMLElement("textarea")}}, and {{HTMLElement("button")}}.</p> + +<p>在进一步讨论之前,先创建一个<a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/getting-started/index.html">简单HTML模板</a>的本地副本—您将在这里输入您的表单HTML。</p> + +<h3 id="HTMLElementform_元素">{{HTMLElement("form")}} 元素</h3> + +<p>所有HTML表单都以一个{{HTMLElement("form")}}元素开始:</p> + +<pre class="brush:html; notranslate"><form action="/my-handling-form-page" method="post"> + +</form></pre> + +<p>这个元素正式定义了一个表单。就像{{HTMLElement("div")}}元素或{{HTMLElement("p")}}元素,它是一个容器元素,但它也支持一些特定的属性来配置表单的行为方式。它的所有属性都是可选的,但实践中最好至少要设置<code>action</code>属性和<code>method</code>属性。</p> + +<ul> + <li><code>action</code> 属性定义了在提交表单时,应该把所收集的数据送给谁(/那个模块)(URL)去处理。.</li> + <li> <code>method</code> 属性定义了发送数据的HTTP方法(它可以是“get”或“post”).</li> +</ul> + +<div class="note"> +<p><strong>注意:</strong>如果您想深入了解这些属性是如何工作的,那么将在<a href="https://developer.mozilla.org/zh-CN/docs/Learn/HTML/Forms/Sending_and_retrieving_form_data">发送表单数据</a>文章中详细说明。</p> +</div> + +<p>现在,将上面的{{htmlelement("form")}} 元素添加到您的HTML主体中</p> + +<h3 id="HTMLelementlabel_HTMLelementinput_和_HTMLelementtextarea_元素">{{HTMLelement("label")}}, {{HTMLelement("input")}} 和 {{HTMLelement("textarea")}} 元素</h3> + +<p>我们的联系人表单非常简单,包含三个文本字段,每个字段都有一个标签。该名称的输入字段将是一个基本的单行文本字段,电子邮件的输入字段将是一个只接受电子邮件地址的单行文本字段,而消息的输入字段将是一个基本的多行文本字段。</p> + +<p>就HTML代码而言,我们需要如下的东西来实现这些表单小部件:</p> + +<pre class="brush:html; notranslate"><form action="/my-handling-form-page" method="post"> +<code> <div> + <label for="name">Name:</label> + <input type="text" id="name"> + </div> + <div> + <label for="mail">E-mail:</label> + <input type="email" id="mail"> + </div> + <div> + <label for="msg">Message:</label> + <textarea id="msg"></textarea> + </div> +</form></code></pre> + +<p>更新您的表单代码,使其看起来像上面的代码。</p> + +<p>使用{{HTMLElement("div")}} 元素可以使我们更加方便地构造我们自己的代码,并且更容易样式化(参见本文后面的文章)。注意在所有{{HTMLElement("label")}}元素上使用<code>for</code>属性;它是将标签链接到表单小部件的一种正规方式。这个属性引用对应的小部件的<code>id</code>。这样做有一些好处。最明显的一个好处是允许用户单击标签以激活相应的小部件。如果您想更好地理解这个属性的其他好处,您可以找到<a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/How_to_structure_an_HTML_form">如何构造HTML表单的详细信息</a>。</p> + +<p>在 {{HTMLElement("input")}}元素中,最重要的属性是<code>type</code> 属性。这个属性非常重要,因为它定义了{{HTMLElement("input")}}属性的行为方式。它可以从根本上改变元素,所以要注意它。稍后您将在<a href="https://developer.mozilla.org/zh-CN/docs/Learn/HTML/Forms/The_native_form_widgets">原生表单控件</a>文章中找到更多关于此的内容。</p> + +<ul> + <li>在我们的简单示例中,我们使用值 <code>text</code> 作为第一个输入——这个属性的默认值。它表示一个基本的单行文本字段,接受任何类型的文本输入。</li> + <li>对于第二个输入,我们使用值<code>email</code>,它定义了一个只接受格式正确的电子邮件地址的单行文本字段。这会将一个基本的文本字段转换为一种“智能”字段,该字段将对用户输入的数据进行一些检查。在稍后的表单数据验证文章中,您将了解到更多关于<a href="https://developer.mozilla.org/zh-CN/docs/Learn/HTML/Forms/Data_form_validation">表单验证</a>的信息。</li> +</ul> + +<p>最后但同样重要的是,要注意<code><input></code> 和 <code><textarea></textarea></code>的语法。这是HTML的一个奇怪之处。 <code><input></code> 标签是一个空元素,这意味着它不需要关闭标签。相反, {{HTMLElement("textarea")}}不是一个空元素,因此必须使用适当的结束标记来关闭它。这对HTML表单的特定特性有影响:定义默认值的方式。要定义{{HTMLElement("input")}}的默认值,你必须使用<code>value</code> 属性,如下所示:</p> + +<pre class="html notranslate"><input type="text" value="by default this element is filled with this text" /></pre> + +<p>相反,如果您想定义{{HTMLElement("textarea")}}的默认值,您只需在{{HTMLElement("textarea")}}元素的开始和结束标记之间放置默认值,就像这样:</p> + +<pre class="html notranslate"><textarea>by default this element is filled with this text</textarea></pre> + +<h3 id="HTMLelementbutton_元素">{{HTMLelement("button")}} 元素</h3> + +<p>我们的表格已经快准备好了,我们只需要再添加一个按钮,让用户在填写完表单后发送他们的数据。这是通过使用 {{HTMLelement("button")}} 元素完成的。在 <code></form>这个结束</code>标签上方添加以下内容:</p> + +<pre class="brush:html; notranslate"><div class="button"> + <button type="submit">Send your message</button> +</div> +</pre> + +<p>您会看到{{htmlelement("button")}}元素也接受一个 <code>type</code>属性,它接受<code>submit</code>, <code>reset</code>或者 <code>button</code> 三个值中的任一个。</p> + +<ul> + <li>单击 <code>type</code> 属性定义为 <code>submit</code> 值(也是默认值)的按钮会发送表单的数据到{{HTMLElement("form")}}元素的<code>action</code> 属性所定义的网页。</li> + <li>单击 <code>type</code> 属性定义为 <code>reset</code> 值的按钮 将所有表单小部件重新设置为它们的默认值。从用户体验的角度来看,这被认为是一种糟糕的做法。</li> + <li>单击 <code>type</code> 属性定义为 <code>button</code> 值的按钮……不会发生任何事!这听起来很傻,但是用JavaScript构建定制按钮非常有用。 </li> +</ul> + +<div class="note"> +<p><strong>注意:</strong>您还可以使用相应类型的 {{HTMLElement("input")}}元素来生成一个按钮,如 <code><input type="submit"></code>。{{htmlelement("button")}}元素的主要优点是, {{HTMLElement("input")}}元素只允许纯文本作为其标签,而{{htmlelement("button")}}元素允许完整的HTML内容,允许更复杂、更有创意的按钮文本。</p> +</div> + +<h2 id="基本表单样式">基本表单样式</h2> + +<p>现在您已经完成了表单的HTML代码,尝试保存它并在浏览器中查看它。<br> + 现在,你会看到它看起来很丑。</p> + +<p><img alt="" src="/files/4049/form-no-style.png" style="height: 170px; width: 534px;"></p> + +<div class="note"> +<p><strong>注意:</strong> 如果你怀疑你的HTML代码不对,试着把它和我们完成的例子进行比较 —— <a href="https://github.com/mdn/learning-area/blob/master/html/forms/your-first-HTML-form/first-form.html">first-form.html</a> (你也可以观看<a href="https://mdn.github.io/learning-area/html/forms/your-first-HTML-form/first-form.html">预览版</a>)。</p> +</div> + +<p>如何排布好表单是公认的难点。这超出了本文的讨论范围,所以现在我们只需要让您添加一些CSS来让它看起来很好。</p> + +<p>首先,在您的HTML头部中添加一个 {{htmlelement("style")}}元素。应该是这样的:</p> + +<pre class="brush:html; notranslate"><style> + +</style></pre> + +<p>在样式标签中,添加如下的CSS,如下所示:</p> + +<pre class="brush:css; notranslate">form { + /* 居中表单 */ + margin: 0 auto; + width: 400px; + /* 显示表单的轮廓 */ + padding: 1em; + border: 1px solid #CCC; + border-radius: 1em; +} + +ul { + list-style: none; + padding: 0; + margin: 0; +} + +form li + li { + margin-top: 1em; +} + +label { + /* 确保所有label大小相同并正确对齐 */ + display: inline-block; + width: 90px; + text-align: right; +} + +input, textarea { + /* 确保所有文本输入框字体相同 + textarea默认是等宽字体 */ + font: 1em sans-serif; + + /* 使所有文本输入框大小相同 */ + width: 300px; + box-sizing: border-box; + + /* 调整文本输入框的边框样式 */ + border: 1px solid #999; +} + +input:focus, textarea:focus { + /* 给激活的元素一点高亮效果 */ + border-color: #000; +} + +textarea { + /* 使多行文本输入框和它们的label正确对齐 */ + vertical-align: top; + + /* 给文本留下足够的空间 */ + height: 5em; +} + +.button { + /* 把按钮放到和文本输入框一样的位置 */ + padding-left: 90px; /* 和label的大小一样 */ +} + +button { + /* 这个外边距的大小与label和文本输入框之间的间距差不多 */ + margin-left: .5em; +}</pre> + +<p>现在,它看起来没那么丑了。</p> + +<p><img alt="" src="https://developer.mozilla.org/files/4051/form-style.png"></p> + +<div class="note"> +<p><strong>注意</strong>: 你可以在GitHub上的这里找到它 <a href="https://github.com/mdn/learning-area/blob/master/html/forms/your-first-HTML-form/first-form-styled.html">first-form-styled.html</a> (<a href="https://mdn.github.io/learning-area/html/forms/your-first-HTML-form/first-form-styled.html">也可以在这儿看运行结果</a>).</p> +</div> + +<h2 id="向您的web服务器发送表单数据">向您的web服务器发送表单数据</h2> + +<p>最后一部分,也许是最棘手的部分,是在服务器端处理表单数据。如前所述,大多数时候HTML表单是向用户请求数据并将其发送到web服务器的一种方便的方式。</p> + +<p>{{HTMLelement("form")}} 元素将定义如何通过<code>action</code> 属性和 <code>method</code>属性来发送数据的位置和方式。</p> + +<p>但这还不够。我们还需要为我们的数据提供一个名称。这些名字对双方都很重要:在浏览器端,它告诉浏览器给数据各自哪个名称,在服务器端,它允许服务器按名称处理每个数据块。</p> + +<p>要将数据命名为表单,您需要在每个表单小部件上使用 <code>name</code> 属性来收集特定的数据块。让我们再来看看我们的表单代码:</p> + +<pre class="brush:html; notranslate"><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_email"> + </div> + <div> + <label for="msg">Message:</label> + <textarea id="msg" name="user_message"></textarea> + </div> + + ...</pre> + +<p>在我们的例子中,表单会发送三个已命名的数据块 "<code>user_name</code>", "<code>user_email</code>", 和 "<code>user_message</code>"。这些数据将用使用<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST">HTTP <code>POST</code></a> 方法,把信息发送到URL为 "<code>/my-handling-form-page</code>"目录下。</p> + +<p>在服务器端,位于URL"<code>/my-handling-form-page</code>" 上的脚本将接收的数据作为HTTP请求中包含的3个键/值项的列表。这个脚本处理这些数据的方式取决于您。每个服务器端语言(PHP、Python、Ruby、Java、c等等)都有自己的机制。深入到这个主题已经超出了本指南的范围,但是如果您想了解更多,我们已经在<a href="/zh-CN/docs/Learn/HTML/Forms/Sending_and_retrieving_form_data">发送表单数据</a>文章中提供了一些示例。 </p> + +<h2 id="总结">总结</h2> + +<p>祝贺您,您已经构建了您的第一个HTML表单。它看起来就像这样:</p> + +<p>{{ EmbedLiveSample('A_simple_form', '100%', '240', '', 'Learn/HTML/Forms/Your_first_HTML_form/Example') }}</p> + +<p>然而,这仅仅是开始,现在是时候深入研究了。HTML表单比我们在这里看到的要强大得多,本指南的其他文章将帮助您掌握其余部分。</p> + +<p>{{NextMenu("Learn/HTML/Forms/How_to_structure_an_HTML_form", "Learn/HTML/Forms")}}</p> diff --git a/files/zh-cn/learn/html/forms_and_buttons/index.html b/files/zh-cn/learn/html/forms_and_buttons/index.html new file mode 100644 index 0000000000..a0f74f6ef1 --- /dev/null +++ b/files/zh-cn/learn/html/forms_and_buttons/index.html @@ -0,0 +1,43 @@ +--- +title: 表单和按钮 +slug: learn/HTML/Forms_and_buttons +tags: + - 初学者 + - 指引 + - 文章 + - 表单 +translation_of: Learn/HTML/Forms_and_buttons +--- +<p>{{draft}}{{LearnSidebar}}</p> + +<p class="summary">表单和按钮是Web的一个非常重要的部分 - 这些允许您的站点访问者输入数据并将其发送给您(例如注册,登录和反馈表单),并且您可以实现控制以控制复杂功能(例如提交表单) 到服务器,或暂停播放视频。)这个模块可以帮助您入门。</p> + +<h2 id="先决条件">先决条件</h2> + +<p>在开始本单元之前,您应该对<a href="/en-US/docs/Learn/HTML/Introduction_to_HTML">HTML的基础知识</a>有一定的了解,如HTML简介中所述。 如果你没有通过这个模块(或类似的东西),先完成它,然后再回来!</p> + +<div class="note"> +<p><strong>Note</strong>: 如果你是在计算机/平板电脑等其他你无法创建文件的设备上的话,你可以尝试在在线代码编辑平台上运行代码例如 <a class="external external-icon" href="http://jsbin.com/" rel="noopener">JSBin</a> 或 <a class="external external-icon" href="https://thimble.mozilla.org/" rel="noopener">Thimble</a>.</p> +</div> + +<h2 id="向导">向导</h2> + +<p>本模块包含以下的文章</p> + +<dl> + <dt><a href="/en-US/docs/Learn/HTML/Forms_and_buttons/Basics">表单和按钮基础知识</a>(Form and button basics)</dt> + <dd> 在本文中,我们将向您介绍HTML表单的基础知识,包括它们的用途,基本功能和常用表单控件。 我们还将了解HTML按钮以及如何使用它们。</dd> + <dt>形成语义和结构</dt> + <dd> 存在许多元素,允许我们将表单结构化为更易于使用和访问 - 其中一些是专门的表单元素,其中一些是通用HTML容器。 在本文中,我们将介绍创建表单结构的最佳实践。</dd> + <dt>高级表单功能</dt> + <dd> 在这里,我们将介绍HTML表单中可用的一些更高级的功能,例如数据列表,进度条,滑块以及最小值和最大值。</dd> + <dt>表格验证</dt> + <dd> 在我们的最终表单文章中,我们将讨论表单验证,讨论为什么有必要,并查看HTML选项卡提供的一些功能,以便客户端验证表单数据。</dd> +</dl> + +<h2 id="练习">练习</h2> + +<dl> + <dt>表单练习</dt> + <dd>等待完成(to be done)</dd> +</dl> diff --git a/files/zh-cn/learn/html/howto/add_a_hit_map_on_top_of_an_image/index.html b/files/zh-cn/learn/html/howto/add_a_hit_map_on_top_of_an_image/index.html new file mode 100644 index 0000000000..450e30b9eb --- /dev/null +++ b/files/zh-cn/learn/html/howto/add_a_hit_map_on_top_of_an_image/index.html @@ -0,0 +1,119 @@ +--- +title: Add a hit map on top of an image +slug: learn/HTML/Howto/Add_a_hit_map_on_top_of_an_image +translation_of: Learn/HTML/Howto/Add_a_hit_map_on_top_of_an_image +--- +<div class="summary"> +<p>现在我们将学习如何设置图像映射,先讨论他的缺点。</p> +</div> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">前提:</th> + <td>你应该已经知道如何<a href="/en-US/Learn/HTML/Write_a_simple_page_in_HTML">create a basic HTML document</a> 以及<a href="/en-US/Learn/HTML/Howto/Add_images_to_a_webpage">add accessible images to a webpage.</a></td> + </tr> + <tr> + <th scope="row">目标:</th> + <td>学习如何将一张图片的不同区域链接到不同页面。</td> + </tr> + </tbody> +</table> + +<div class="warning"> +<p>本文仅讨论客户端图像映射。不要使用服务器端图像映射,这需要用户拥有鼠标。</p> +</div> + +<h2 id="图像映射和它的缺点">图像映射和它的缺点</h2> + +<p>当你在{{htmlelement('a')}}标签中嵌套图像, 整个图像是链接到一个网页的。但在图像映射中,包含多个活动区域(称为“热点”),可以链接到不同的资源地址。</p> + +<p>图像映射原本非常流行于导航策略,但是前提需要考虑它的性能和可访问性。</p> + +<p><a href="https://developer.mozilla.org/en-US/Learn/HTML/Howto/Create_a_hyperlink">Text links</a> (perhaps styled with CSS) 比图像映射更具优势:文本链接更轻量级、好维护、更易于SEO,而且支持更多形式需求的访问(如,屏幕阅读器、纯文本浏览器、翻译服务等)。</p> + +<h2 id="如何正确的插入一张图像映射">如何正确的插入一张图像映射</h2> + +<h3 id="步骤1_图片">步骤1: 图片</h3> + +<p>不是所有图片都合适。</p> + +<ul> + <li>图片必须明确表明当用户跟随图片链接时会发生什么。 <code>alt</code> 属性是必须的, 但很多人注意不到。</li> + <li>图片必须明确指出热点的开始和结束位置。</li> + <li>在任何尺寸的视口下,热点都需要足够大,方便用户可以点击。多大足够呢?<a href="http://uxmovement.com/mobile/finger-friendly-design-ideal-mobile-touch-target-sizes/">72 × 72 CSS pixels 是一个推荐的最小尺寸,</a> 包括触摸目标之间额外的间隙。在 <a href="http://www.goethe-verlag.com/book2/">50languages.com</a> (as of time of writing) 上的世界地图可以完美诠释这一点。 用户点击Russia 或 North America 要比 Albania 或 Estonia容易得多。</li> +</ul> + +<p>插入图片的方式 <a href="http://developer.mozilla.org/en-US/Learn/HTML/Howto/Add_images_to_a_webpage">和通常一样</a> (用 {{htmlelement("img")}} 标签 和 {{htmlattrxref("alt",'img')}} 文本). 如果图片只是用作导航容器, 你可以设置图片的 <code>alt="", 改在后面</code>{{htmlelement('area')}} 的{{htmlattrxref("alt",'area')}} 中提供合适的文本。</p> + +<p>你将需要一个特殊的 {{htmlattrxref("usemap","img")}} 属性。 为图像映射提供一个唯一标识,这个标识不能包含空格。将这个标识 (preceded by a hash) 作为 <code>usemap</code> 属性的值:</p> + +<pre class="brush: html"><img + src="image-map.png" + alt="" + usemap="#example-map-1" /></pre> + +<h3 id="步骤2_激活你的热点">步骤2: 激活你的热点</h3> + +<p>在这一步中, 将所有代码放置 {{htmlelement('map')}} 标签中. <code><map></code> 只需要一个属性, 设置{{htmlattrxref("name","map")}} 和上面<code>usemap属性一样的map值:</code></p> + +<pre class="brush: html"><map name="example-map-1"> + +</map></pre> + +<p><code>在<map></code> 元素中,我们需要嵌套 {{htmlelement('area')}} 元素。一个 <code><area></code> 元素对应一个热点.。为保持键盘导航的直观, 请确保<code><area></code> 的源顺序和视觉上的热点顺序一致。</p> + +<p><code><area></code> 元素是空元素, 但是需要包含4个属性:</p> + +<dl> + <dt>{{htmlattrxref('shape','area')}}</dt> + <dt>{{htmlattrxref('coords','area')}}</dt> + <dd> + <p><code>shape</code> 有4个值: <code>circle</code>, <code>rect</code>, <code>poly</code>, and <code>default</code>. ( <code>default</code> <code><area></code> 表示除去您定义的其他热点的剩余空间.) 根据你选择的形状需要在 <code>coords</code> 中提供对应的坐标信息。</p> + + <ul> + <li>对于circle, 提供中心的x、y坐标,还需要提供半径。</li> + <li>对于rectangle, 提供左上角和右下角的x、y坐标。</li> + <li>对于polygon, 提供每个角的x、y坐标(至少6个值)。</li> + </ul> + + <p>坐标用CSS像素px表示。</p> + + <p>In case of overlap, source order carries the day.</p> + </dd> + <dt>{{htmlattrxref('href','area')}}</dt> + <dd>您需要链接的资源地址。 如果您不希望当前区域链接到任何地方(比方说,如果您正在创建一个空心圆),您可以将这个属性保留为空。</dd> + <dt>{{htmlattrxref('alt','area')}}</dt> + <dd>一个必选属性,告诉用户链接的指向或功能说明。<code>alt</code> 文本仅在图像不可用时显示。请参阅我们的<a href="https://developer.mozilla.org/en-US/Learn/HTML/Howto/Create_a_hyperlink#Writing_accessible_link_text">guidelines for writing accessible link text</a>。</dd> + <dd> + <p>如果 <code>href</code> 属性为空并且整个图像已经具备了<code>alt</code> 属性,则可以设置 <code>alt=""。</code></p> + </dd> +</dl> + +<pre class="brush: html"><map name="example-map-1"> + <area shape="circle" coords="200,250,25" + href="page-2.html" alt="circle example" /> + + + <area shape="rect" coords="10, 5, 20, 15" + href="page-3.html" alt="rectangle example" /> + +</map></pre> + +<h3 id="步骤3_确保它的可用范围">步骤3: 确保它的可用范围</h3> + +<p>你还并没有完成除非你很严格的在多个浏览器和终端测试图像映射功能。尝试仅用键盘操作。尝试关掉图片。</p> + +<p>如果你的图像映射宽度大于240px,你将需要进一步调整来适应网站的响应式。仅调整小屏幕下的图片是不够的,因为不变的坐标无法适应这样的图像。</p> + +<p>如果必须使用图像映射, 您可以看看<a href="https://github.com/stowball/jQuery-rwdImageMaps">Matt Stow's jQuery plugin.</a>。另外, Dudley Storey 示范了一种方法 <a href="http://thenewcode.com/696/Using-SVG-as-an-Alternative-To-Imagemaps">use SVG for an image map effect</a>,以及后来的<a href="http://thenewcode.com/760/Create-A-Responsive-Imagemap-With-SVG">ombined SVG-raster hack</a> for bitmap images.</p> + +<h2 id="Learn_more">Learn more</h2> + +<ul> + <li>{{htmlelement("img")}}</li> + <li>{{htmlelement("map")}}</li> + <li>{{htmlelement("area")}}</li> + <li><a href="http://www.maschek.hu/imagemap/imgmap">Online image map editor</a></li> + <li><a href="http://blog.goolara.com/2014/06/05/image-maps-revisited/">Advice on handling email clients</a></li> +</ul> diff --git a/files/zh-cn/learn/html/howto/index.html b/files/zh-cn/learn/html/howto/index.html new file mode 100644 index 0000000000..cf467bb4cf --- /dev/null +++ b/files/zh-cn/learn/html/howto/index.html @@ -0,0 +1,157 @@ +--- +title: 使用 HTML 解决常见问题 +slug: learn/HTML/Howto +tags: + - HTML + - 常见问题 +translation_of: Learn/HTML/Howto +--- +<div>{{LearnSidebar}}</div> + +<p class="summary">下面的链接指向日常中需要用HTML解决的问题的解决方案。</p> + +<div class="column-container"> +<div class="column-half"> +<h3 id="基本结构">基本结构</h3> + +<p>HTML应用最基础的是文档结构。如果你是HTML新手那么你应该和我们一起从这里开始学习.</p> + +<ul> + <li><a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/Getting_started#实践操作_创建你的第一个HTML文档">如何创建HTML文档</a></li> + <li><a href="/en-US/docs/Learn/HTML/Howto/Divide_a_webpage_into_logical_sections">如何将网页分成有逻辑的段落</a></li> + <li><a href="/en-US/Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals#The_basics_headings_and_paragraphs">如何设置一个适当的标题和段落结构</a></li> +</ul> + +<h3 id="基本文本语义">基本文本语义</h3> + +<p>HTML专门为文档提供语义信息,因此,HTML能够解答关于如何在文档中最好地传递消息的许多问题。</p> + +<ul> + <li><a href="/en-US/Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals#Lists">如何用HTML创建列表项</a></li> + <li><a href="/en-US/Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals#Emphasis_and_importance">如何强调或凸显内容</a></li> + <li><a href="/en-US/Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals#Emphasis_and_importance">如何表明文本是重要的</a></li> + <li><a href="/en-US/Learn/HTML/Introduction_to_HTML/Advanced_text_formatting#Representing_computer_code">如何用HTML展示计算机代码</a></li> + <li><a href="/en-US/Learn/HTML/Multimedia_and_embedding/Images_in_HTML#Annotating_images_with_figures_and_figure_captions">如何注释图片和图标</a></li> + <li><a href="/en-US/Learn/HTML/Introduction_to_HTML/Advanced_text_formatting#Abbreviations">如何注解缩略语并使其可理解</a></li> + <li><a href="/en-US/Learn/HTML/Introduction_to_HTML/Advanced_text_formatting#Quotations">如何为网页添加引述和引用</a></li> + <li><a href="/en-US/docs/Learn/HTML/Howto/Define_terms_with_HTML">如何用HTML定义术语</a></li> +</ul> +</div> + +<div class="column-half"> +<h3 id="超链接">超链接</h3> + +<p>使用HTML的主要原因之一,就是可以使用{{Glossary("hyperlink", "hyperlinks")}}来轻松导航,实现方式有以下几种:</p> + +<ul> + <li><a href="/en-US/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks">如何创建超链接</a></li> + <li><a href="/en-US/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks#Active_learning_creating_a_navigation_menu">如何利用HTML创建表格</a></li> +</ul> + +<h3 id="图像_多媒体">图像 & 多媒体</h3> + +<ul> + <li><a href="/en-US/Learn/HTML/Multimedia_and_embedding/Images_in_HTML#How_do_we_put_an_image_on_a_webpage">如何在页面中添加图片</a></li> + <li><a href="/en-US/Learn/HTML/Multimedia_and_embedding/Video_and_audio_content">如何在页面中添加视频</a></li> + <li><font color="#0b0116"><a href="/en-US/Learn/HTML/Multimedia_and_embedding/Video_and_audio_content">如何在页面中添加音频</a></font></li> +</ul> + +<h3 id="脚本_样式">脚本 & 样式</h3> + +<p>HTML仅仅建立了文档结构。为解决演示文稿问题,可使用{{glossary("CSS")}}或脚本令页面交互。</p> + +<ul> + <li><a href="/en-US/Learn/CSS/Introduction_to_CSS/How_CSS_works#How_to_apply_your_CSS_to_your_HTML">如何在网页中使用CSS</a></li> + <li><a href="/en-US/docs/Learn/HTML/Howto/Use_JavaScript_within_a_webpage">如何在网页中使用JavaScript</a></li> +</ul> + +<h3 id="嵌入内容">嵌入内容</h3> + +<ul> + <li><a href="/en-US/Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies">如何在网页中嵌入另一个页面</a></li> + <li><a href="/en-US/Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies#The_%3Cembed%3E_and_%3Cobject%3E_elements">如何在网页中加入Flash内容</a></li> +</ul> +</div> +</div> + +<h2 id="进阶问题">进阶问题</h2> + +<p>除了基本问题,HTML还有更丰富的功能,其提供了高级特性用于解决复杂问题.这些文章可以帮助你解决一些相对不常见的问题:</p> + +<div class="column-container"> +<div class="column-half"> +<h3 id="表单">表单</h3> + +<p>表单是一种复杂的HTML结构,用于从网页向网络服务器发送数据.我们鼓励你仔细阅读<a href="/en-US/docs/Web/Guide/HTML/Forms">完整指南</a>.你可由此入门:</p> + +<ul> + <li><a href="/en-US/docs/Web/Guide/HTML/Forms/My_first_HTML_form">如何创建一个简单的网页表单</a></li> + <li><a href="/en-US/docs/Web/Guide/HTML/Forms/How_to_structure_an_HTML_form">如何结构化一个网页表单</a></li> +</ul> + +<h3 id="表格信息">表格信息</h3> + +<p>一些表格化信息/数据需用行和列整合到表格中去. 而表格是最复杂的HTML结构之一,熟练掌握它并不容易:</p> + +<ul> + <li><a href="/en-US/docs/Learn/HTML/Howto/Create_a_data_spreadsheet">如何创建一张数据电子表格</a></li> + <li><a href="/en-US/docs/Learn/HTML/Howto/Make_HTML_tables_accessible">如何使HTML表格可获取</a></li> + <li><a href="/en-US/docs/Learn/HTML/Howto/Optimize_HTML_table_rendering">如何优化HTML表格的展现</a></li> +</ul> + +<h3 id="数据表示">数据表示</h3> + +<ul> + <li><a href="/en-US/docs/Learn/HTMLHowto/Represent_numeric_values_with_HTML">如何用HTML表示数值</a></li> + <li><a href="/en-US/docs/Learn/HTML/Howto/Use_data_attributes">如何使用数据属性</a></li> + <li><a href="/en-US/docs/Learn/HTML/Howto/Associate_human_readable_content_with_arbitrary_computer_data_structures">如何关联人类可读内容与无序的计算机数据结构</a></li> +</ul> + +<h3 id="互动">互动</h3> + +<ul> + <li><a href="/en-US/docs/Learn/HTML/Howto/Create_collapsible_content_with_HTML">如何用HTML创建收缩内容</a></li> + <li><a href="/en-US/docs/Learn/HTML/Howto/Add_context_menus_to_a_webpage">如何为网页添加内容目录</a></li> + <li><a href="/en-US/docs/Learn/HTML/Howto/Create_dialog_boxes_with_HTML">如何用HTML创建对话框</a></li> +</ul> +</div> + +<div class="column-half"> +<h3 id="高级文本语义">高级文本语义</h3> + +<ul> + <li><a href="/en-US/docs/Learn/HTML/Howto/Take_control_of_HTML_line_breaking">如何控制HTML换行</a></li> + <li><a href="/en-US/docs/Learn/HTML/Howto/Mark_text_insertion_and_deletion">如何标注更改(新增和已删除文本)</a></li> +</ul> + +<h3 id="高级图像_多媒体">高级图像 & 多媒体</h3> + +<ul> + <li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images">如何为网页添加可响应图像</a></li> + <li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web">如何为网页添加矢量图像</a></li> + <li><a href="/en-US/docs/Learn/HTML/Howto/Add_a_hit_map_on_top_of_an_image">如何在图像上添加热区</a></li> +</ul> + +<h3 id="国际化">国际化</h3> + +<p>HTML支持多语言. 其提供了用于解决常见的国际化问题的工具.</p> + +<ul> + <li><a href="/en-US/docs/Learn/HTML/Howto/Add_multiple_languages_into_a_single_webpage">如何为单一网页添加多语言支持</a></li> + <li><a href="/en-US/docs/Learn/HTML/Howto/Handle_Japanese_ruby_characters">如何处理日语字符</a></li> + <li><a href="/en-US/docs/Learn/HTML/Howto/Display_time_and_date_with_HTML">如何用HTML展现时间和日期</a></li> +</ul> + +<h3 id="性能">性能</h3> + +<ul> + <li><a href="/en-US/docs/Learn/HTML/Howto/Author_fast-loading_HTML_pages">如何创造快速加载的HTML页面</a></li> +</ul> +</div> +</div> + +<p><span style="display: none;"> </span><span style="display: none;"> </span><span style="display: none;"> </span><span style="display: none;"> </span> </p> + +<p> + <audio style="display: none;"></audio> +</p> diff --git a/files/zh-cn/learn/html/index.html b/files/zh-cn/learn/html/index.html new file mode 100644 index 0000000000..6e4c0162a8 --- /dev/null +++ b/files/zh-cn/learn/html/index.html @@ -0,0 +1,57 @@ +--- +title: 学习 HTML :指南与教程 +slug: learn/HTML +tags: + - HTML + - HTML5 + - 主题 + - 入门指导 + - 基础 + - 学习 + - 新手 + - 简介 +translation_of: Learn/HTML +--- +<div>{{LearnSidebar}}</div> + +<p class="summary">为了创建网站,你应该了解 {{Glossary('HTML')}} —— 用于定义一个网页结构的基本技术。HTML 用于表示你的网页内容是应该被理解为段落、列表、头部、链接、图像、多媒体播放器、表单或是其他众多可用的元素之一亦或是你定义的新元素。</p> + +<h2 id="学习路径">学习路径</h2> + +<p>理论上来说你的学习旅途应该从学 HTML 开始。先阅读 <a href="https://developer.mozilla.org/zh-CN/docs/Learn/HTML/Introduction_to_HTML">HTML 介绍</a>。此后你便能够继续学习更多高级的主题,例如:</p> + +<ul> + <li><a href="https://developer.mozilla.org/zh-CN/docs/Learn/CSS">CSS </a>,以及如何用它装饰 HTML (例如:更改你的文本字号和字体,添加边框和阴影,将你的页面设计成多栏布局,添加动画和其他视觉效果。)</li> + <li><a href="https://developer.mozilla.org/zh-CN/docs/Learn/JavaScript">JavaScript</a> ,以及如何用它为网页添加动态功能(例如:找到你的地址并且在地图上绘制出来,触发按钮时让 UI 元素显示或消失,将用户的数据本地储存在他们的电脑里,以及更多。)</li> +</ul> + +<p>在开始这个主题的学习之前,你至少要基本熟悉使用电脑和被动地使用网络(即单纯地查看内容)。你应该设置好一个基础的工作环境,详细参照<a href="https://developer.mozilla.org/zh-CN/docs/Learn/Getting_started_with_the_web/Installing_basic_software">安装基础软件</a>,并且理解如何新建和管理文件,详细参照<a href="https://developer.mozilla.org/zh-CN/docs/Learn/Getting_started_with_the_web/Dealing_with_files">文件处理</a>——这两者都在 <a href="https://developer.mozilla.org/zh-CN/docs/Learn/Getting_started_with_the_web">Web 入门</a>的完全新手模块里。</p> + +<p>在尝试学习这个主题之前,建议先完成 <a href="https://developer.mozilla.org/zh-CN/docs/Learn/Getting_started_with_the_web">Web 入门</a>,不过这并不是绝对必要的。<a href="https://developer.mozilla.org/zh-CN/docs/Learn/Getting_started_with_the_web/HTML_basics">HTML 基础 </a>里大多数的文章在 <a href="https://developer.mozilla.org/zh-CN/docs/Learn/HTML/Introduction_to_HTML">HTML 介绍</a> 模块里也有,虽然有很多额外的细节。</p> + +<h2 id="模块">模块</h2> + +<p>这个主题由包含以下模块,建议按顺序进行学习。很显然,你要从第一个开始。</p> + +<dl> + <dt><a href="https://developer.mozilla.org/zh-CN/docs/Learn/HTML/Introduction_to_HTML">HTML 介绍</a></dt> + <dd>这一模块将为你铺路,帮你习惯一些重要的概念和语法,着眼于如何对文本应用 HTML ,如何创造超链接,以及如何使用 HTML 构造一个网页。</dd> + <dt><a href="https://developer.mozilla.org/zh-CN/docs/Learn/HTML/Multimedia_and_embedding">多媒体与嵌入</a></dt> + <dd>这个模块带你探索如何使用 HTML 在你的网页里如何包含多媒体信息,包含如何用各种方法包含图片,以及如何嵌入视频、音频,甚至是嵌入其他完整的网页。</dd> + <dt><a href="https://developer.mozilla.org/zh-CN/docs/Learn/HTML/Tables">HTML 表格</a></dt> + <dd>在网页上用易于理解和可访问({{glossary("Accessibility", "accessible")}})的方式来表示表格数据是一项挑战。这个模块包括了基本的表格标记,还有更多复杂的特性,例如实现标题和总结。</dd> + <dt><a href="https://developer.mozilla.org/zh-CN/docs/Learn/HTML/Forms">HTML 表单</a></dt> + <dd>表单是网页中十分重要的一部分——它们会提供网站交互需要的很多功能(例如:注册,登录,发送反馈,购物等等)。这个模块将带你开始创建表单的客户端部分。</dd> +</dl> + +<h2 id="解决常见的_HTML_问题">解决常见的 HTML 问题</h2> + +<p><a href="https://developer.mozilla.org/zh-CN/docs/Learn/HTML/Howto">使用 HTML 解决常见问题</a>提供了一系列在创建网页过程中遇到的常见问题的解决方案:处理标题,添加图片或视频,强调内容,创建一个基础表单等等。</p> + +<h2 id="相关链接">相关链接</h2> + +<dl> + <dt>MDN 上的 <a href="https://developer.mozilla.org/zh-CN/docs/Web/HTML">HTML(超文本标记语言)</a></dt> + <dd>这是 HTML 文档在 MDN 上的主入口,涵盖了详细的元素和属性参考——比如说如果你想知道一个元素有什么属性或者一个属性有什么值,这是一个查询它们的好地方。</dd> + <dt></dt> +</dl> diff --git a/files/zh-cn/learn/html/introduction_to_html/advanced_text_formatting/index.html b/files/zh-cn/learn/html/introduction_to_html/advanced_text_formatting/index.html new file mode 100644 index 0000000000..cbeed8e8a0 --- /dev/null +++ b/files/zh-cn/learn/html/introduction_to_html/advanced_text_formatting/index.html @@ -0,0 +1,632 @@ +--- +title: 高阶文字排版 +slug: learn/HTML/Introduction_to_HTML/Advanced_text_formatting +tags: + - 上下标 + - 代码 + - 引文 + - 引用 + - 描述列表 + - 缩略语 +translation_of: Learn/HTML/Introduction_to_HTML/Advanced_text_formatting +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/Creating_hyperlinks", "Learn/HTML/Introduction_to_HTML/文件和网站结构", "Learn/HTML/Introduction_to_HTML")}}</div> + +<p class="summary">HTML中有许多其他元素可以用于格式化文本,我们没有在<a href="https://developer.mozilla.org/zh-CN/docs/Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals">HTML 文字处理基础</a>中提到它们。本文中所描述的元素虽然少有人知,但仍然值得去学习(尽管仍然不是完整的列表)。在这里你将了解标记引文、描述列表、计算机代码和其他相关文本、下标和上标、联系信息等。</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">预备知识:</th> + <td>熟悉 HTML 基础(包含在 <a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/Getting_started">开始学习 HTML</a> 中)、HTML 文本格式(包含在 <a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/HTML_text_fundamentals">HTML 文字处理初步</a> 中)。</td> + </tr> + <tr> + <th scope="row">目标:</th> + <td>学习一些不常见的 HTML 元素标记来使用高级语义功能。</td> + </tr> + </tbody> +</table> + +<h2 id="描述列表">描述列表</h2> + +<p>在 HTML 基础部分,我们讨论了如何在 HTML 中<a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals#列表_Lists">标记基本的列表</a>,但是我们没有提到你偶尔会遇到的第三种类型的列表—<strong>描述列表</strong> (description list) <strong>。</strong>这种列表的目的是标记一组项目及其相关描述,例如术语和定义,或者是问题和答案等。让我们看一组术语和定义的示例:</p> + +<pre class="notranslate">内心独白 +戏剧中,某个角色对自己的内心活动或感受进行念白表演,这些台词只面向观众,而其他角色不会听到。 +语言独白 +戏剧中,某个角色把自己的想法直接进行念白表演,观众和其他角色都可以听到。 +旁白 +戏剧中,为渲染幽默或戏剧性效果而进行的场景之外的补充注释念白,只面向观众,内容一般都是角色的感受、想法、以及一些背景信息等。</pre> + +<p>描述列表使用与其他列表类型不同的闭合标签— {{htmlelement("dl")}}; 此外,每一项都用 {{htmlelement("dt")}} (description term) 元素闭合。每个描述都用 {{htmlelement("dd")}} (description description) 元素闭合。让我们来完成下面的标记例子:</p> + +<pre class="brush: html notranslate"><dl> + <dt>内心独白</dt> + <dd>戏剧中,某个角色对自己的内心活动或感受进行念白表演,这些台词只面向观众,而其他角色不会听到。</dd> + <dt>语言独白</dt> + <dd>戏剧中,某个角色把自己的想法直接进行念白表演,观众和其他角色都可以听到。</dd> + <dt>旁白</dt> + <dd>戏剧中,为渲染幽默或戏剧性效果而进行的场景之外的补充注释念白,只面向观众,内容一般都是角色的感受、想法、以及一些背景信息等。</dd> +</dl></pre> + +<p>浏览器的默认样式会在<strong>描述列表的描述部分</strong>(description description)和<strong>描述术语</strong>(description terms)之间产生缩进。MDN非常严密地遵循这一惯例,同时也鼓励关于术语的其他更多的定义(but also embolden the terms for extra definition)。</p> + +<p>下面是前述代码的显示结果:</p> + +<dl> + <dt>内心独白</dt> + <dd>戏剧中,某个角色对自己的内心活动或感受进行念白表演,这些台词只面向观众,而其他角色不会听到。</dd> + <dt>语言独白</dt> + <dd>戏剧中,某个角色把自己的想法直接进行念白表演,观众和其他角色都可以听到。</dd> + <dt>旁白</dt> + <dd>戏剧中,为渲染幽默或戏剧性效果而进行的场景之外的补充注释念白,只面向观众,内容一般都是角色的感受、想法、以及一些背景信息等。</dd> +</dl> + +<p>请注意:一个术语 <code><dt></code> 可以同时有多个描述 <code><dd></code>,比如说:</p> + +<dl> + <dt>旁白</dt> + <dd>戏剧中,为渲染幽默或戏剧性效果而进行的场景之外的补充注释念白,只面向观众,内容一般都是角色的感受、想法、以及一些背景信息等。</dd> + <dd>写作中,指与当前主题相关的一段内容,通常不适于直接置于内容主线中,因此置于附近的其它位置(通常位于主线内容旁边一个文本框内)。</dd> +</dl> + +<h3 id="主动学习_标记一组定义">主动学习: 标记一组定义</h3> + +<p>现在是时候尝试一下描述列表了; 在输入区域的原始文本里添加相应的元素,使得它在输出区域是以描述列表的形式出现。如果你喜欢,你也可以使用你自己的描述术语和描述。</p> + +<p>如果你做错了,你可以随时点击【重置】按钮。如果实在进行不下去,可以点击【显示答案】。</p> + +<div class="hidden"> +<h6 id="Playable_code">Playable code</h6> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html lang="zh-CN"> + <head> + <meta charset="utf-8"> + <style> + body { font-family: '微软雅黑', Helvetica, Arial, sans-serif; margin: 10px; background: #f5f9fa; } + h2 { font-size: 16px; } + code, textarea { font-family: Consolas, Menlo, monospace; } + .output { min-height: 160px; } + .input { min-height: 160px; width: 95%; } + .a11y-label { margin: 0; text-align: right; font-size: 0.7rem; width: 98%; } + .controls { width: 96%; text-align: right; } + </style> + + </head> + <body> + <h2>实时输出</h2> + <div class="output"></div> + + <h2>可编辑代码</h2> + <p class="a11y-label">按 ESC 退出编辑区域,按 Tab 可插入制表符 <code>'\t'</code> </p> + <textarea id="code" class="input"></textarea> + + <div class="controls"> + <button id="btn-reset">重置</button> + <button id="btn-solution">显示答案</button> + </div> + <script> + const btnReset = document.getElementById('btn-reset'); + const btnSolution = document.getElementById('btn-solution'); + const blockOutput = document.querySelector('.output'); + const blockInput = document.querySelector('.input'); + const original = +`培根 +整个世界的粘合剂。 +鸡蛋 +一块蛋糕的粘合剂。 +咖啡 +一种浅棕色的饮料。 +可以在清晨带来活力。`; + const answer = +`<dl> + <dt>培根</dt> + <dd>整个世界的粘合剂。</dd> + <dt>鸡蛋</dt> + <dd>一块蛋糕的粘合剂。</dd> + <dt>咖啡</dt> + <dd>一种浅棕色的饮料。</dd> + <dd>可以在清晨带来活力。</dd> +</dl>`; + let userEntry = ""; + + init(); + btnReset.addEventListener('click', init); + + btnSolution.addEventListener('click', () => { + if (btnSolution.textContent === '显示答案') { + blockInput.value = + blockOutput.innerHTML = answer; + btnSolution.textContent = '隐藏答案'; + } else { + blockInput.value = + blockOutput.innerHTML = userEntry; + btnSolution.textContent = '显示答案'; + } + }); + + blockInput.addEventListener('keydown', (e) => { + switch (e.key) { + case 'Tab': + e.preventDefault(); + insertAtCursor('\t'); + break; + case "Escape": + blockInput.blur(); + break; + } + }); + + blockInput.addEventListener('keyup', () => { + userEntry = blockInput.value; + blockOutput.innerHTML = blockInput.value; + if (btnSolution.textContent === '隐藏答案') { + btnSolution.textContent = '显示答案'; + } + }); + + function init() { + userEntry = + blockOutput.innerHTML = + blockInput.value = original; + btnSolution.textContent = '显示答案'; + } + + function insertAtCursor(text) { + const scrollPos = blockInput.scrollTop; + const cursorPos = blockInput.selectionStart; + + const front = blockInput.value.substring(0, cursorPos); + const back = blockInput.value.substring( + blockInput.selectionEnd, blockInput.value.length); + + blockInput.value = front + text + back; + blockInput.selectionStart = + blockInput.selectionEnd = cursorPos + text.length; + blockInput.focus(); + blockInput.scrollTop = scrollPos; + } + </script> + </body> +</html></pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code', 700, 500, "", "", "hide-codepen-jsfiddle") }}</p> + +<h2 id="引用">引用</h2> + +<p>HTML也有用于标记引用的特性,至于使用哪个元素标记,取决于你引用的是一块还是一行。</p> + +<h3 id="块引用">块引用</h3> + +<p>如果一个块级内容(一个段落、多个段落、一个列表等)从其他地方被引用,你应该把它用{{htmlelement("blockquote")}}元素包裹起来表示,并且在{{htmlattrxref("cite","blockquote")}}属性里用URL来指向引用的资源。例如,下面的例子就是引用的MDN的<code><blockquote></code>元素页面:</p> + +<pre class="brush: html notranslate"><p>The <strong>HTML <code>&lt;blockquote&gt;</code> Element</strong> (or <em>HTML Block +Quotation Element</em>) indicates that the enclosed text is an extended quotation.</p></pre> + +<p>要把这些转换为块引用,我们要这样做:</p> + +<pre class="brush: html notranslate"><blockquote cite="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/blockquote"> + <p>The <strong>HTML <code>&lt;blockquote&gt;</code> Element</strong> (or <em>HTML Block + Quotation Element</em>) indicates that the enclosed text is an extended quotation.</p> +</blockquote></pre> + +<p>浏览器在渲染块引用时默认会增加缩进,作为引用的一个指示符;MDN是这样做的,但是也增加了额外的样式:</p> + +<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> + +<h3 id="行内引用">行内引用</h3> + +<p>行内元素用同样的方式工作,除了使用{{htmlelement("q")}}元素。例如,下面的标记包含了从MDN<code><q></code>页面的引用:</p> + +<pre class="brush: html notranslate"><p>The quote element — <code>&lt;q&gt;</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> +</pre> + +<p>浏览器默认将其作为普通文本放入引号内表示引用,就像下面:</p> + +<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>(<q>元素旨在用于不需要分段的短引用)</p> + +<h3 id="引文">引文</h3> + +<p>{{htmlattrxref("cite","blockquote")}}属性内容不会被浏览器显示、屏幕阅读器阅读,需使用 JavaScript 或 CSS,浏览器才会显示<code>cite</code>的内容。如果你想要确保引用的来源在页面上是可显示的,更好的方法是为{{htmlelement("cite")}}元素附上链接:</p> + +<pre class="brush: html notranslate"><p>According to the <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/blockquote"> +<cite>MDN blockquote page</cite></a>: +</p> + +<blockquote cite="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/blockquote"> + <p>The <strong>HTML <code>&lt;blockquote&gt;</code> Element</strong> (or <em>HTML Block + Quotation Element</em>) indicates that the enclosed text is an extended quotation.</p> +</blockquote> + +<p>The quote element — <code>&lt;q&gt;</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> -- <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/q"> +<cite>MDN q page</cite></a>.</p> +</pre> + +<p>引文默认的字体样式为斜体。你可以在<a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/advanced-text-formatting/quotations.html">quotations.html</a>中参看代码。</p> + +<h3 id="主动学习:是谁说的?">主动学习:是谁说的?</h3> + +<p>到了主动学习的时间!在这个例子中我们想要你:</p> + +<ol> + <li>把中间的段落变成块引用,它要包含<code>cite</code>属性</li> + <li>把第三个段落的一部分变成行内引用,它要包含<code>cite</code>属性</li> + <li>每一个引用都要包含<code><cite></code>元素</li> +</ol> + +<p>你需要的引用源:</p> + +<ul> + <li>http://www.brainyquote.com/quotes/authors/c/confucius.html 对应 "孔子曰"。</li> + <li>http://www.affirmationsforpositivethinking.com/ 对应 "不要说泄气的话"。</li> +</ul> + +<p>如果你做错了,你可以随时点击【重置】按钮。如果实在进行不下去,可以点击【显示答案】。</p> + +<div class="hidden"> +<h6 id="Playable_code_2">Playable code 2</h6> + +<pre class="brush: html notranslate"><code><!DOCTYPE html> +<html lang="zh-CN"> + <head> + <meta charset="utf-8"> + <style> + body { font-family: '微软雅黑', Helvetica, Arial, sans-serif; margin: 10px; background: #f5f9fa; } + h2 { font-size: 16px; } + code, textarea { font-family: Consolas, Menlo, monospace; } + .output { min-height: 160px; } + .input { min-height: 160px; width: 95%; } + .a11y-label { margin: 0; text-align: right; font-size: 0.7rem; width: 98%; } + .controls { width: 96%; text-align: right; } + </style> + + </head> + <body> + <h2>实时输出</h2> + <div class="output"></div> + + <h2>可编辑代码</h2> + <p class="a11y-label">按 ESC 退出编辑区域,按 Tab 可插入制表符 <code>'\t'</code> </p> + <textarea id="code" class="input"></textarea> + + <div class="controls"> + <button id="btn-reset">重置</button> + <button id="btn-solution">显示答案</button> + </div> + <script> + const btnReset = document.getElementById('btn-reset'); + const btnSolution = document.getElementById('btn-solution'); + const blockOutput = document.querySelector('.output'); + const blockInput = document.querySelector('.input'); + const original = +`<p>你好!欢迎访问我的激励网页!孔子曰:</p> +<p>譬如为山,未成一篑,止,吾止也。譬如平地,虽覆一篑,进,吾往也。</p> +<p>要保持乐观,不要说泄气的话。(源自 Affirmations for Positive Thinking。)</p>`; + const answer = +`<p>你好!欢迎访问我的激励网页!<a href="</code>http://www.brainyquote.com/quotes/authors/c/confucius.html<code>"><cite>孔子</cite></a>曰:</p> +<blockquote cite="https://zh.wikipedia.org/zh-hans/孔子"> + <p>譬如为山,未成一篑,止,吾止也。譬如平地,虽覆一篑,进,吾往也。</p> +</blockquote> +<p>要保持乐观,<q cite="http://www.affirmationsforpositivethinking.com/">不要说泄气的话</q>。(源自 <a href="http://www.affirmationsforpositivethinking.com/"><cite>Affirmations for Positive Thinking</cite></a>。)</p>`; + let userEntry = ""; + + init(); + btnReset.addEventListener('click', init); + + btnSolution.addEventListener('click', () => { + if (btnSolution.textContent === '显示答案') { + blockInput.value = + blockOutput.innerHTML = answer; + btnSolution.textContent = '隐藏答案'; + } else { + blockInput.value = + blockOutput.innerHTML = userEntry; + btnSolution.textContent = '显示答案'; + } + }); + + blockInput.addEventListener('keydown', (e) => { + switch (e.key) { + case 'Tab': + e.preventDefault(); + insertAtCursor('\t'); + break; + case "Escape": + blockInput.blur(); + break; + } + }); + + blockInput.addEventListener('keyup', () => { + userEntry = blockInput.value; + blockOutput.innerHTML = blockInput.value; + if (btnSolution.textContent === '隐藏答案') { + btnSolution.textContent = '显示答案'; + } + }); + + function init() { + userEntry = + blockOutput.innerHTML = + blockInput.value = original; + btnSolution.textContent = '显示答案'; + } + + function insertAtCursor(text) { + const scrollPos = blockInput.scrollTop; + const cursorPos = blockInput.selectionStart; + + const front = blockInput.value.substring(0, cursorPos); + const back = blockInput.value.substring( + blockInput.selectionEnd, blockInput.value.length); + + blockInput.value = front + text + back; + blockInput.selectionStart = + blockInput.selectionEnd = cursorPos + text.length; + blockInput.focus(); + blockInput.scrollTop = scrollPos; + } + </script> + </body> +</html></code></pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code_2', 700, 500, "", "", "hide-codepen-jsfiddle") }}</p> + +<h2 id="缩略语">缩略语</h2> + +<p>另一个你在web上看到的相当常见的元素是{{htmlelement("abbr")}}——它常被用来包裹一个缩略语或缩写,并且提供缩写的解释(包含在{{htmlattrxref("title")}}属性中)。让我们看看下面两个例子:</p> + +<pre class="brush: html notranslate"><p>我们使用 <abbr title="超文本标记语言(Hyper text Markup Language)">HTML</abbr> 来组织网页文档。</p> + +<p>第 33 届 <abbr title="夏季奥林匹克运动会">奥运会</abbr> 将于 2024 年 8 月在法国巴黎举行。</p> +</pre> + +<p>这些代码的显示效果如下(当光标移动到项目上时会出现提示):</p> + +<p>我们使用 <abbr title="超文本标记语言(Hypertext Markup Language)">HTML</abbr> 来组织网页文档。</p> + +<p>第 33 届 <abbr title="夏季奥林匹克运动会">奥运会</abbr> 将于 2024 年 8 月在法国巴黎举行。</p> + +<div class="note"> +<p><strong>Note</strong>: 还有另一个元素<acronym>,它基本上与<abbr>相同,专门用于首字母缩略词而不是缩略语。 然而,这已经被废弃了 - 它在浏览器的支持中不如<abbr>,并且具有类似的功能,所以没有意义。 只需使用<abbr>。</p> +</div> + +<h3 id="主动学习:标记一个缩略语">主动学习:标记一个缩略语</h3> + +<p>在这个简单的主动学习任务中,我们希望你简单地标记一个缩写。你可以使用下面的示例,或者用自己的示例来替换。</p> + +<div class="hidden"> +<h6 id="Playable_code_3">Playable code 3</h6> + +<pre class="brush: html notranslate"><code><!DOCTYPE html> +<html lang="zh-CN"> + <head> + <meta charset="utf-8"> + <style> + body { font-family: '微软雅黑', Helvetica, Arial, sans-serif; margin: 10px; background: #f5f9fa; } + h2 { font-size: 16px; } + code, textarea { font-family: Consolas, Menlo, monospace; } + .output { min-height: 100px; } + .input { min-height: 100px; width: 95%; } + .a11y-label { margin: 0; text-align: right; font-size: 0.7rem; width: 98%; } + .controls { width: 96%; text-align: right; } + </style> + + </head> + <body> + <h2>实时输出</h2> + <div class="output"></div> + + <h2>可编辑代码</h2> + <p class="a11y-label">按 ESC 退出编辑区域,按 Tab 可插入制表符 <code>'\t'</code> </p> + <textarea id="code" class="input"></textarea> + + <div class="controls"> + <button id="btn-reset">重置</button> + <button id="btn-solution">显示答案</button> + </div> + <script> + const btnReset = document.getElementById('btn-reset'); + const btnSolution = document.getElementById('btn-solution'); + const blockOutput = document.querySelector('.output'); + const blockInput = document.querySelector('.input'); + const original = '<p>NASA 做了一些动人心弦的事情。</p>'; + const answer = '<p><abbr title="美国国家航空航天局(National Aeronautics and Space Administration)">NASA</abbr> 做了一些动人心弦的事情。</p>'; + let userEntry = ""; + + init(); + btnReset.addEventListener('click', init); + + btnSolution.addEventListener('click', () => { + if (btnSolution.textContent === '显示答案') { + blockInput.value = + blockOutput.innerHTML = answer; + btnSolution.textContent = '隐藏答案'; + } else { + blockInput.value = + blockOutput.innerHTML = userEntry; + btnSolution.textContent = '显示答案'; + } + }); + + blockInput.addEventListener('keydown', (e) => { + switch (e.key) { + case 'Tab': + e.preventDefault(); + insertAtCursor('\t'); + break; + case "Escape": + blockInput.blur(); + break; + } + }); + + blockInput.addEventListener('keyup', () => { + userEntry = blockInput.value; + blockOutput.innerHTML = blockInput.value; + if (btnSolution.textContent === '隐藏答案') { + btnSolution.textContent = '显示答案'; + } + }); + + function init() { + userEntry = + blockOutput.innerHTML = + blockInput.value = original; + btnSolution.textContent = '显示答案'; + } + + function insertAtCursor(text) { + const scrollPos = blockInput.scrollTop; + const cursorPos = blockInput.selectionStart; + + const front = blockInput.value.substring(0, cursorPos); + const back = blockInput.value.substring( + blockInput.selectionEnd, blockInput.value.length); + + blockInput.value = front + text + back; + blockInput.selectionStart = + blockInput.selectionEnd = cursorPos + text.length; + blockInput.focus(); + blockInput.scrollTop = scrollPos; + } + </script> + </body> +</html></code></pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code_3', 700, 400, "", "", "hide-codepen-jsfiddle") }}</p> + +<h2 id="标记联系方式">标记联系方式</h2> + +<p>HTML有个用于标记联系方式的元素——{{htmlelement("address")}}。它仅仅包含你的联系方式,例如:</p> + +<pre class="brush: html notranslate"><address> + <p>Chris Mills, Manchester, The Grim North, UK</p> +</address></pre> + +<p>但要记住的一点是,<code><address></code>元素是为了标记编写HTML文档的人的联系方式,而不是任何其他的内容。因此,如果这是Chris写的文档,上面的内容将会很好。注意,下面的内容也是可以的:</p> + +<pre class="brush: html notranslate"><address> + <p>Page written by <a href="../authors/chris-mills/">Chris Mills</a>.</p> +</address></pre> + +<h2 id="上标和下标">上标和下标</h2> + +<p>当你使用日期、化学方程式、和数学方程式时会偶尔使用上标和下标。 {{htmlelement("sup")}} 和{{htmlelement("sub")}}元素可以解决这样的问题。例如:</p> + +<pre class="brush: html notranslate"><p>咖啡因的化学方程式是 C<sub>8</sub>H<sub>10</sub>N<sub>4</sub>O<sub>2</sub>。</p> +<p>如果 x<sup>2</sup> 的值为 9,那么 x 的值必为 3 或 -3。</p> +</pre> + +<p>这些代码输出的结果是:</p> + +<p>咖啡因的化学方程式是 C<sub>8</sub>H<sub>10</sub>N<sub>4</sub>O<sub>2</sub>。</p> + +<p>如果 x<sup>2</sup> 的值为 9,那么 x 的值必为 3 或 -3。</p> + +<h2 id="展示计算机代码">展示计算机代码</h2> + +<p>有大量的HTML元素可以来标记计算机代码:</p> + +<ul> + <li>{{htmlelement("code")}}: 用于标记计算机通用代码。</li> + <li>{{htmlelement("pre")}}: 用于保留空白字符(通常用于代码块)——如果您在文本中使用缩进或多余的空白,浏览器将忽略它,您将不会在呈现的页面上看到它。但是,如果您将文本包含在<code><pre></pre></code>标签中,那么空白将会以与你在文本编辑器中看到的相同的方式渲染出来。</li> + <li>{{htmlelement("var")}}: 用于标记具体变量名。</li> + <li>{{htmlelement("kbd")}}: 用于标记输入电脑的键盘(或其他类型)输入。</li> + <li>{{htmlelement("samp")}}: 用于标记计算机程序的输出。</li> +</ul> + +<p>让我们看看一些例子。你应该尝试运行一下(尝试运行一下<a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/advanced-text-formatting/other-semantics.html">other-semantics.html</a>样例文件的拷贝):</p> + +<pre class="brush: html notranslate"><pre><code>const para = document.querySelector('p'); + +para.onclick = function() { + alert('噢,噢,噢,别点我了。'); +}</code></pre> + +<p>请不要使用 <code>&lt;font&gt;</code> 、 <code>&lt;center&gt;</code> 等表象元素。</p> + +<p>在上述的 JavaScript 示例中,<var>para</var> 表示一个段落元素。</p> + + +<p>按 <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> +</pre> + +<p>上面的代码显示效果如下:</p> + +<p>{{ EmbedLiveSample('展示计算机代码','100%',300, "", "", "hide-codepen-jsfiddle") }}</p> + +<h2 id="标记时间和日期">标记时间和日期</h2> + +<p>HTML 还支持将时间和日期标记为可供机器识别的格式的 {{htmlelement("time")}} 元素。例如:</p> + +<pre class="brush: html notranslate"><<span class="pl-ent">time</span> <span class="pl-e">datetime</span>=<span class="pl-s"><span class="pl-pds">"</span>2016-01-20<span class="pl-pds">"</span></span>>2016年1月20日</<span class="pl-ent">time</span>></pre> + +<p>为什么需要这样做?因为世界上有许多种书写日期的格式,上边的日期可能被写成:</p> + +<ul> + <li>20 January 2016</li> + <li>20th January 2016</li> + <li>Jan 20 2016</li> + <li>20/06/16</li> + <li>06/20/16</li> + <li>The 20th of next month</li> + <li><span lang="fr">20e Janvier 2016</span></li> + <li><span lang="ja">2016年1月20日</span></li> + <li><span lang="ja">And so on</span></li> +</ul> + +<p>但是这些不同的格式不容易被电脑识别 — 假如你想自动抓取页面上所有事件的日期并将它们插入到日历中,{{htmlelement("time")}} 元素允许你附上清晰的、可被机器识别的 时间/日期来实现这种需求。</p> + +<p>上述基本的例子仅仅提供了一种简单的可被机器识别的日期格式,这里还有许多其他支持的格式,例如:</p> + +<pre class="brush: html notranslate"><!-- 标准简单日期 --> +<<span class="pl-ent">time</span> <span class="pl-e">datetime</span>=<span class="pl-s"><span class="pl-pds">"</span>2016-01-20<span class="pl-pds">"</span></span>>20 January 2016</<span class="pl-ent">time</span>> +<!-- 只包含年份和月份--> +<<span class="pl-ent">time</span> <span class="pl-e">datetime</span>=<span class="pl-s"><span class="pl-pds">"</span>2016-01<span class="pl-pds">"</span></span>>January 2016</<span class="pl-ent">time</span>> +<!-- 只包含月份和日期 --> +<<span class="pl-ent">time</span> <span class="pl-e">datetime</span>=<span class="pl-s"><span class="pl-pds">"</span>01-20<span class="pl-pds">"</span></span>>20 January</<span class="pl-ent">time</span>> +<!-- 只包含时间,小时和分钟数 --> +<<span class="pl-ent">time</span> <span class="pl-e">datetime</span>=<span class="pl-s"><span class="pl-pds">"</span>19:30<span class="pl-pds">"</span></span>>19:30</<span class="pl-ent">time</span>> +<!-- 还可包含秒和毫秒 --> +<<span class="pl-ent">time</span> <span class="pl-e">datetime</span>=<span class="pl-s"><span class="pl-pds">"</span></span>19:30:01.856<span class="pl-s"><span class="pl-pds">"</span></span>>19:30:01.856</<span class="pl-ent">time</span>> +<!-- 日期和时间 --> +<<span class="pl-ent">time</span> <span class="pl-e">datetime</span>=<span class="pl-s"><span class="pl-pds">"</span>2016-01-20T19:30<span class="pl-pds">"</span></span>>7.30pm, 20 January 2016</<span class="pl-ent">time</span>> +<!-- 含有时区偏移值的日期时间 --> +<<span class="pl-ent">time</span> <span class="pl-e">datetime</span>=<span class="pl-s"><span class="pl-pds">"</span>2016-01-20T19:30<span class="pl-pds">+01:00"</span></span>>7.30pm, 20 January 2016 is 8.30pm in France</<span class="pl-ent">time</span>> +<!-- 调用特定的周 --> +<<span class="pl-ent">time</span> <span class="pl-e">datetime</span>=<span class="pl-s"><span class="pl-pds">"</span>2016-W04<span class="pl-pds">"</span></span>>The fourth week of 2016</<span class="pl-ent">time</span>></pre> + +<h2 id="总结">总结</h2> + +<p>到这里你就完成了 HTML 语义文本元素的学习。但要记住,你在本课程中学到的并不是 HTML 文本元素的详细列表 — 我们想要尽量覆盖主要的、通用的、常见的,或者至少是有趣的部分。如果你想找到更多的 HTML 元素,可以看一看我们的<a href="/zh-CN/docs/Web/HTML/Element">HTML 元素参考</a>(从 <a href="/zh-CN/docs/Web/HTML/Element#内联文本语义">内联文本语义</a>部分开始会是一个好的选择) 。在下一篇文章中我们将会学习用来组织 HTML 文档不同部分的 HTML 元素。</p> + +<p>{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/Creating_hyperlinks", "Learn/HTML/Introduction_to_HTML/文件和网站结构", "Learn/HTML/Introduction_to_HTML")}}</p> + +<h2 id="本章目录">本章目录</h2> + +<ul> + <li><a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/Getting_started">开始学习 HTML</a></li> + <li><a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML">“头”里有什么?HTML 元信息</a></li> + <li><a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/HTML_text_fundamentals">HTML 文字处理初步</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks">创建超链接</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Advanced_text_formatting">高级文字格式</a></li> + <li><a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/文件和网站结构">文档和站点结构</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Debugging_HTML">HTML 调试</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Marking_up_a_letter">课程测验:为信件排版</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Structuring_a_page_of_content">课程测验:构建内容丰富的网页</a></li> +</ul> diff --git a/files/zh-cn/learn/html/introduction_to_html/creating_hyperlinks/index.html b/files/zh-cn/learn/html/introduction_to_html/creating_hyperlinks/index.html new file mode 100644 index 0000000000..63ad5724ad --- /dev/null +++ b/files/zh-cn/learn/html/introduction_to_html/creating_hyperlinks/index.html @@ -0,0 +1,323 @@ +--- +title: 建立超链接 +slug: Learn/HTML/Introduction_to_HTML/Creating_hyperlinks +tags: + - HTML指南 + - URL + - 超链接 +translation_of: Learn/HTML/Introduction_to_HTML/Creating_hyperlinks +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals", "Learn/HTML/Introduction_to_HTML/Advanced_text_formatting", "Learn/HTML/Introduction_to_HTML")}}</div> + +<p class="summary"><span id="result_box" lang="zh-CN"><span>超链接非常重要 ——它们使互联网成为一个互联的网络。</span><span>本文介绍了创建链接所需的语法,并且讨论了链接的最佳实现方法。</span></span></p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">前提:</th> + <td>熟悉基本HTML(包含在<a href="https://wiki.developer.mozilla.org/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Getting_started"> 开始学习HTML</a>中),HTML 文本格式(包含在 <a href="https://wiki.developer.mozilla.org/zh-CN/docs/Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals">HTML文字基础</a> 中)。</td> + </tr> + <tr> + <th scope="row">目标:</th> + <td>学习如何实现一个有效地把多个文件链接在一起的超文本链接。</td> + </tr> + </tbody> +</table> + +<h2 id="什么是超链接">什么是超链接?</h2> + +<p><span id="result_box" lang="zh-CN"><span>超链接是互联网提供的最令人兴奋的创新之一,</span><span>它们从一开始就一直是互联网的一个特性,使互联网成为互联的网络。超链接使我们能够将我们的文档链接到任何其他文档(或其他资源),也可以链接</span><span>到文档的指定部分,我们可以在一个简单的网址上提供应用程序(与必须先安装的本地应用程序或其他东西相比)。几乎任何网络内容都可以转换为链接,</span><span>点击(或激活)超链接将使网络浏览器转到另一个网址({{glossary("URL")}})。</span></span></p> + +<div class="note"> +<p>注意:URL可以指向HTML文件、文本文件、图像、文本文档、视频和音频文件以及可以在网络上保存的任何其他内容。 如果浏览器不知道如何显示或处理文件,它会询问您是否要打开文件(需要选择合适的本地应用来打开或处理文件)或下载文件(以后处理它)。</p> +</div> + +<p><span lang="zh-CN"><span>以 BBC 的主页为例,里面就包含了非常多的连结,各自连到不同新闻、网站的其它地方(导览功能),或者登入/注册页面等等。</span></span></p> + +<p><img alt="frontpage of bbc.co.uk, showing many news items, and navigation menu functionality" src="https://mdn.mozillademos.org/files/17032/updated-bbc-website.png"></p> + +<h2 id="链接的解析"><span class="short_text" id="result_box" lang="zh-CN"><span>链接的解析</span></span></h2> + +<p><span id="result_box" lang="zh-CN"><span>通过将文本(或其他内容,见{{anch("块级链接")}})转换为{{htmlelement("a")}}元素内的链接来创建基本链接,</span> <span>给它一个{{htmlattrxref("href", "a")}}属性(也称为目标),它将包含您希望链接指向的网址。</span></span></p> + +<pre class="brush: html notranslate"><p>我创建了一个指向 +<a href="https://www.mozilla.org/zh-CN/">Mozilla 主页</a> +的超链接。 +</p></pre> + +<p><span class="short_text" id="result_box" lang="zh-CN"><span>结果如下所示:</span></span></p> + +<p>我创建了一个指向 <a href="https://www.mozilla.org/zh-CN/">Mozilla 主页</a> 的超链接。</p> + +<h3 id="使用title属性添加支持信息"><span class="short_text" id="result_box" lang="zh-CN"><span>使用title属性添加支持信息</span></span></h3> + +<p><span id="result_box" lang="zh-CN"><span>您可能要添加到您的链接的另一个属性是标题;</span><span>这旨在包含关于链接的补充有用信息,例如页面包含什么样的信息或需要注意的事情。</span> <span>例如:</span></span></p> + +<pre class="brush: html notranslate"><p>我创建了一个指向 +<a href="https://www.mozilla.org/zh-CN/" + title="了解 Mozilla 使命以及如何参与贡献的最佳站点。">Mozilla 主页</a> +的超链接。 +</p></pre> + +<p><span class="short_text" id="result_box" lang="zh-CN"><span>结果如下(当鼠标指针悬停在链接上时,标题将作为提示信息出现):</span></span></p> + +<p>我创建了一个指向 <a href="https://www.mozilla.org/zh-CN/">Mozilla 主页</a> 的超链接。</p> + +<div class="note"> +<p>注意:链接的标题仅当鼠标悬停在其上时才会显示,这意味着使用键盘来导航网页的人很难获取到标题信息。如果标题信息对于页面非常重要,你应该使用所有用户能都方便获取的方式来呈现,例如放在常规文本中。</p> +</div> + +<h3 id="主动学习:创建您自己的示例链接"><span class="short_text" id="result_box" lang="zh-CN"><span>主动学习:创建您自己的示例链接</span></span></h3> + +<p><span class="short_text" id="result_box" lang="zh-CN"><span>主动学习时间:我们希望您使用本地代码编辑器创建一个HTML文档(我们的</span></span> <a href="https://github.com/roy-tian/learning-area/blob/master/html/introduction-to-html/getting-started/index.html">入门模板</a> 很适合<span class="short_text" lang="zh-CN"><span>)</span></span></p> + +<ul> + <li>在HTML内,尝试添加一个或者多个段落或其他你知道类型的内容。</li> + <li>将某些内容转换为链接。</li> + <li>包含标题属性。</li> +</ul> + +<h3 id="块级链接">块级链接</h3> + +<p>如上所述,你可以将一些内容转换为链接,甚至是<a href="/zh-CN/docs/Web/HTML/Block-level_elements">块级元素</a>。例如你想要将一个图像转换为链接,你只需把图像元素放到<code><a></a></code>标签中间。</p> + +<pre class="brush: html notranslate"><a href="https://www.mozilla.org/zh-CN/"> + <img src="mozilla-image.png" alt="链接至 Mozilla 主页的 Mozilla 标志"> +</a></pre> + +<div class="note"> +<p><strong>注意</strong>: 你会在未来的文章中发现更多在Web中使用图像的例子。</p> +</div> + +<h2 id="统一资源定位符URL与路径path快速入门">统一资源定位符(URL)与路径(path)快速入门</h2> + +<p>要全面地了解链接目标,你需要了解统一资源定位符和文件路径。本小节将介绍相关的信息。</p> + +<p>统一资源定位符(英文:<strong>U</strong>niform <strong>R</strong>esource <strong>L</strong>ocator,简写:URL)是一个定义了在网络上的位置的一个文本字符串。例如 Mozilla 的中文主页定位在 <code>https://www.mozilla.org/zh-CN/</code>.</p> + +<p>URL使用路径查找文件。路径指定文件系统中您感兴趣的文件所在的位置。看一下一个简单的目录结构的例子(源码可查看 <a href="https://github.com/roy-tian/learning-area/tree/master/html/introduction-to-html/creating-hyperlinks">创建超链接(creating-hyperlinks</a>)。)<img alt="A simple directory structure. The parent directory is called creating-hyperlinks and contains two files called index.html and contacts.html, and two directories called projects and pdfs, which contain an index.html and a project-brief.pdf file, respectively" src="https://mdn.mozillademos.org/files/12409/simple-directory.png" style="display: block; margin: 0 auto;"></p> + +<p>此目录结构的<strong>根目录</strong>称为<code>creating-hyperlinks</code>。当在网站上工作时, 你会有一个包含整个网站的目录。在根目录,我们有一个<code>index.html</code>和一个<code>contacts.html</code>文件。在真实的网站上,<code>index.html</code> 将会成为我们的主页或登录页面。</p> + +<p>我们的根目录还有两个目录—— <code>pdfs</code> 和<code>projects</code>,它们分别包含一个 PDF (<code>project-brief.pdf</code>) 文件和一个<code>index.html</code> 文件。请注意你可以有两个<code>index.html</code>文件,前提是他们在不同的目录下,许多网站就是如此。第二个<code>index.html</code>或许是项目相关信息的主登录界面。</p> + +<ul> + <li> + <p><strong>指向当前目录:</strong>如果<code>index.html</code>(目录顶层的<code>index.html</code>)想要包含一个超链接指向<code>contacts.html</code>,你只需要指定想要链接的文件名,因为它与当前文件是在同一个目录的. 所以你应该使用的URL是<code>contacts.html</code>:</p> + + <pre class="brush: html notranslate"><p>要联系某位工作人员,请访问我们的 <a href="contacts.html">联系人页面</a>。</p> +</pre> + </li> + <li> + <p><strong>指向子目录:</strong>如果<code>index.html</code> (目录顶层<code>index.html</code>)想要包含一个超链接指向 <code>projects/index.html</code>,您需要先进入<code>projects/</code>项目目录,然后指明要链接到的文件<code>index.html</code>。 通过指定目录的名称,然后是正斜杠,然后是文件的名称。因此您要使用的URL是<code>projects/index.html</code>:</p> + + <pre class="brush: html notranslate"><p>请访问 <a href="projects/index.html">项目页面</a>。</p></pre> + </li> + <li> + <p><strong>指向上级目录: </strong>如果你想在<code>projects/index.html</code>中包含一个指向<code>pdfs/project-brief.pdf</code>的超链接,你必须先返回上级目录,然后再回到<code>pdf</code>目录。“返回上一个目录级”使用两个英文点号表示 — <code>..</code> — 所以你应该使用的URL是 <code>../pdfs/project-brief.pdf</code>:</p> + + <pre class="brush: html notranslate"><p>点击打开 <a href="../pdfs/project-brief.pdf">项目简介</a>。</p></pre> + </li> +</ul> + +<div class="note"> +<p>注意:如果需要的话,你可以将这些功能的多个例子和复杂的url结合起来。例如:<code>../../../complex/path/to/my/file.html</code>.</p> +</div> + +<h3 id="文档片段">文档片段</h3> + +<p>超链接除了可以链接到文档外,也可以链接到HTML文档的特定部分(被称为<strong>文档片段</strong>)<span>。要做到这一点,你必须首先给要链接到的元素分配一个</span>{{htmlattrxref("id")}}<span>属性。例如,如果你想链接到一个特定的标题,可以这样做:</span></p> + +<pre class="brush: html notranslate"><h2 id="Mailing_address">邮寄地址</h2></pre> + +<p>然后链接到那个特定的<code>id</code>,您可以在URL的结尾使用一个井号指向它,例如:</p> + +<pre class="brush: html notranslate"><p>要提供意见和建议,请将信件邮寄至 <a href="contacts.html#Mailing_address">我们的地址</a>。</p></pre> + +<p>你甚至可以在同一份文档下,通过链接文档片段,来链接到同一份文档的另一部分:</p> + +<pre class="brush: html notranslate"><p>本页面底部可以找到 <a href="#Mailing_address">公司邮寄地址</a>。</p></pre> + +<h3 id="绝对URL和相对URL">绝对<span><strong>URL</strong></span>和相对<span><strong>URL</strong></span></h3> + +<p><span>你可能会在网络上遇到两个术语,<strong>绝对URL</strong>和<strong>相对URL</strong><em>(或者称为,<strong>绝对链接</strong>和<strong>相对链接</strong>)</em>:</span></p> + +<p><strong>绝对URL</strong>:指向由其在Web上的绝对位置定义的位置,包括 {{glossary("protocol")}}(协议) 和 {{glossary("domain name")}}(域名)。像下面的例子,如果<code>index.html</code>页面上传到<code>projects</code>这一个目录。并且<code>projects</code>目录位于web服务站点的根目录,web站点的域名为<code>http://www.example.com</code>,那么这个页面就可以通过<code>http://www.example.com/projects/index.html</code>访问(或者通过<code>http://www.example.com/projects/</code>来访问,因为在没有指定特定的URL的情况下,大多数web服务会默认访问加载<code>index.html</code>这类页面)</p> + +<p>不管绝对URL在哪里使用,它总是指向确定的相同位置。</p> + +<p><strong>相对URL</strong>:指向与您链接的文件相关的位置,更像我们在前面一节中所看到的位置。例如,如果我们想从示例文件链接<code>http://www.example.com/projects/index.html</code>转到相同目录下的一个PDF文件,URL就是文件名URL——例如<code>project-brief.pdf</code>——没有其他的信息要求。如果PDF文件能够在<code>projects</code>的子目录<code>pdfs</code>中访问到,相对路径就是<code>pdfs/project-brief.pdf</code>(对应的绝对URL是<code>http://www.example.com/projects/pdfs/project-brief.pdf</code>)</p> + +<p>一个相对URL将指向不同的位置,这取决于它所在的文件所在的位置——例如,如果我们把<code>index.html</code>文件从<code>projects</code>目录移动到Web站点的根目录(最高级别,而不是任何目录中),里面的<code>pdfs/project-brief.pdf</code>相对URL将会指向<code>http://www.example.com/pdfs/project-brief.pdf</code>,而不是<code>http://www.example.com/projects/pdfs/project-brief.pdf</code></p> + +<p>当然,<code>project-brief.pdf</code>文件和<code>pdfs</code>文件夹的位置不会因为您移动了<code>index.html</code>文件而突然发生变化——这将使您的链接指向错误的位置,因此如果单击它,它将无法工作。你得小心点!</p> + +<h2 id="链接最佳实践">链接最佳实践</h2> + +<p>下面是一些在编写链接元素时可以遵循的最佳实践。</p> + +<ul> +</ul> + +<h3 id="使用清晰的链接措辞">使用清晰的链接措辞</h3> + +<p>把链接放在你的页面上很容易。这还不够。我们需要让所有的读者都可以使用链接,不管他们当前的环境和哪些工具。例如:</p> + +<ul> + <li>使用屏幕阅读器的用户喜欢从页面上的一个链接跳到另一个链接,并且脱离上下文来阅读链接。</li> + <li>搜索引擎使用链接文本来索引目标文件,所以在链接文本中包含关键词是一个很好的主意,以有效地描述与之相关的信息。</li> + <li>读者往往会浏览页面而不是阅读每一个字,他们的眼睛会被页面的特征所吸引,比如链接。他们会找到描述性的链接。</li> +</ul> + +<p>下面是一个具体的例子:</p> + +<p><em><strong>好的</strong>链接文本:</em> <a href="https://firefox.com/">下载Firefox</a></p> + +<pre class="brush: html notranslate"><p><a href="https://firefox.com/"> + 下载Firefox +</a></p></pre> + +<p><em><strong>不好的</strong>链接文本:</em> <a href="https://firefox.com/">点击这里</a>下载Firefox</p> + +<pre class="brush: html notranslate"><p><a href="https://firefox.com/"> + 点击这里 +</a> +下载Firefox</p> +</pre> + +<p>其他提示:</p> + +<ul> + <li>不要重复URL作为链接文本的一部分 ——URL看起来很丑,当屏幕朗读器一个字母一个字母的读出来的时候听起来就更丑了。</li> + <li>不要在链接文本中说“链接”或“链接到”——它只是噪音。屏幕阅读器告诉人们有一个链接。可视化用户也会知道有一个链接,因为链接通常是用不同的颜色设计的,并且存在下划线(这个惯例一般不应该被打破,因为用户习惯了它。)</li> + <li>保持你的链接标签尽可能短——长链接尤其惹恼屏幕阅读器用户,他们必须听到整件事读出来。</li> +</ul> + +<h3 id="尽可能使用相对链接">尽可能使用相对链接</h3> + +<p>从上面的描述中,您可能认为始终使用绝对链接是一个好主意;毕竟,当页面像相对链接那样移动时,它们不会中断。但是,当链接到同一网站的其他位置时,你应该使用相对链接(当链接到另一个网站时,你需要使用绝对链接):</p> + +<ul> + <li>首先,检查代码要容易得多——相对URL通常比绝对URL短得多,这使得阅读代码更容易。</li> + <li>其次,在可能的情况下使用相对URL更有效。当使用绝对URL时,浏览器首先通过{{glossary("DNS")}}(见<a href="/zh-CN/docs/Learn/Getting_started_with_the_web/How_the_Web_works">万维网是如何工作的</a>)查找服务器的真实位置,然后再转到该服务器并查找所请求的文件。另一方面,相对URL,浏览器只在同一服务器上查找被请求的文件。因此,如果你使用绝对URL而不是相对URL,你就会不断地让你的浏览器做额外的工作,这意味着它的效率会降低。</li> +</ul> + +<h3 id="链接到非HTML资源_——留下清晰的指示">链接到非HTML资源 ——留下清晰的指示</h3> + +<p>当链接到一个需要下载的资源(如PDF或Word文档)或流媒体(如视频或音频)或有另一个潜在的意想不到的效果(打开一个弹出窗口,或加载Flash电影),你应该添加明确的措辞,以减少任何混乱。如下的例子会让人反感:</p> + +<ul> + <li>如果你是在低带宽连接,点击一个链接,然后就开始下载大文件。</li> + <li>如果你没有安装Flash播放器,点击一个链接,然后突然被带到一个需要Flash的页面。</li> +</ul> + +<p>让我们看看一些例子,看看在这里可以使用什么样的文本:</p> + +<pre class="brush: html notranslate"><p><a href="http://www.example.com/large-report.pdf"> + 下载销售报告(PDF, 10MB) +</a></p> + +<p><a href="http://www.example.com/video-stream/"> + 观看视频(将在新标签页中播放, HD画质) +</a></p> + +<p><a href="http://www.example.com/car-game"> + 进入汽车游戏(需要Flash插件) +</a></p></pre> + +<h3 id="在下载链接时使用_download_属性">在下载链接时使用 download 属性</h3> + +<p>当您链接到要下载的资源而不是在浏览器中打开时,您可以使用 download 属性来提供一个默认的保存文件名(译注:此属性仅适用于<a href="/zh-CN/docs/Web/Security/Same-origin_policy">同源URL</a>)。下面是一个下载链接到Firefox 的 Windows最新版本的示例:</p> + +<pre class="notranslate"><code><a href="https://download.mozilla.org/?product=firefox-latest-ssl&os=win64&lang=zh-CN" + download="firefox-latest-64bit-installer.exe"> + 下载最新的 Firefox 中文版 - Windows(64位) +</a></code></pre> + +<h2 id="主动学习:创建一个导航菜单">主动学习:创建一个导航菜单</h2> + +<p>在这个练习中,我们希望你把一些页面和导航菜单链接起来,创建一个多页面的网站。这是创建网站的一种常见方式——每一页都使用相同的页面结构,包括相同的导航菜单,所以当链接被点击时,它给人的印象是你停留在同一个地方,不同的内容正在被提出来。</p> + +<p>您需要将以下四页的本地副本放在同一目录中。 (see the <a href="https://github.com/roy-tian/learning-area/tree/master/html/introduction-to-html/navigation-menu-start">navigation-menu-start</a> directory if you want a the full listing):</p> + +<ul> + <li><a href="https://github.com/roy-tian/learning-area/blob/master/html/introduction-to-html/navigation-menu-start/index.html">index.html</a></li> + <li><a href="https://github.com/roy-tian/learning-area/blob/master/html/introduction-to-html/navigation-menu-start/projects.html">projects.html</a></li> + <li><a href="https://github.com/roy-tian/learning-area/blob/master/html/introduction-to-html/navigation-menu-start/pictures.html">pictures.html</a></li> + <li><a href="https://github.com/roy-tian/learning-area/blob/master/html/introduction-to-html/navigation-menu-start/social.html">social.html</a></li> +</ul> + +<p>你应该:</p> + +<ol> + <li>在一个页面上的指定位置添加一个无序列表,其中包含要链接到的页面的名称。导航菜单通常只是一个链接列表,因此这在语义上是确定的。</li> + <li>将每个页面名称转换为该页的链接。</li> + <li>将导航菜单复制到每个页面。</li> + <li>在每一页上,只删除同一页的链接——一个页面包含自己的链接是令人困惑和毫无意义的,而缺少链接会对你当前的页面起到很好的视觉提示作用。</li> +</ol> + +<p>最终的例子应该是这样的:</p> + +<p><img alt="简单的HTML导航菜单,包含主页、图片、项目、社交四个项目。" src="https://mdn.mozillademos.org/files/17395/navigation_example_cn.png" style="display: block; margin: 0 auto;"></p> + +<div class="note"> +<p><strong>注意</strong>: 如果你卡住了,或者不确定你是否正确,你可以检查导航菜单上的目录,看看正确的答案。</p> +</div> + +<h2 id="电子邮件链接">电子邮件链接</h2> + +<p>当点击一个链接或按钮时,打开一个新的电子邮件发送信息而不是连接到一个资源或页面,这种情况是可能做到的。这样做是使用{{HTMLElement("a")}}元素和<code>mailto</code>:URL的方案。<br> + 其最基本和最常用的使用形式为一个<code>mailto</code>:link (链接),链接简单说明收件人的电子邮件地址。例如:</p> + +<pre class="brush: html notranslate"><a href="mailto:nowhere@mozilla.org">向 nowhere 发邮件</a> +</pre> + +<p>这会创建一个链接,看起来像这样: <a href="mailto:nowhere@mozilla.org">向 nowhere 发邮件</a>。</p> + +<p>实际上,邮件地址甚至是可选的。如果你忘记了(也就是说,你的{{htmlattrxref("href", "a")}}仅仅只是简单的"<code>mailto:</code>"),一个新的发送电子邮件的窗口也会被用户的邮件客户端打开,只是没有收件人的地址信息,这通常在“分享”链接是很有用的,用户可以发送给他们选择的地址邮件</p> + +<h3 id="具体细节">具体细节</h3> + +<p>除了电子邮件地址,您还可以提供其他信息。事实上,任何标准的邮件头字段可以被添加到你提供的邮件URL。 其中最常用的是主题(subject)、抄送(cc)和主体(body) (这不是一个真正的头字段,但允许您为新邮件指定一个短内容消息)。 每个字段及其值被指定为查询项。</p> + +<p>下面是一个包含cc、bcc、主题和主体的示例:</p> + +<pre class="brush: html notranslate"><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></pre> + +<div class="note"> +<p><strong>注意:</strong> 每个字段的值必须是URL编码的。 也就是说,不能有非打印字符(不可见字符比如制表符、换行符、分页符)和空格 <a href="http://en.wikipedia.org/wiki/Percent-encoding">percent-escaped</a>. 同时注意使用问号(<code>?</code>)来分隔主URL与参数值,以及使用&符来分隔<code>mailto:</code>中的各个参数。 这是标准的URL查询标记方法。阅读 <a href="/zh-CN/docs/Learn/HTML/Forms/Sending_and_retrieving_form_data#GET_方法">GET 方法</a> 以了解哪种URL查询标记方法是更常用的。</p> +</div> + +<p>这里有一些其他的示例<code>mailto</code>链接:</p> + +<ul> + <li><a href="mailto:">mailto:</a></li> + <li><a href="mailto:nowhere@mozilla.org">mailto:nowhere@mozilla.org</a></li> + <li><a href="mailto:nowhere@mozilla.org,nobody@mozilla.org">mailto:nowhere@mozilla.org,nobody@mozilla.org</a></li> + <li><a href="mailto:nowhere@mozilla.org?cc=nobody@mozilla.org">mailto:nowhere@mozilla.org?cc=nobody@mozilla.org</a></li> + <li><a href="mailto:nowhere@mozilla.org?cc=nobody@mozilla.org&subject=This%20is%20the%20subject">mailto:nowhere@mozilla.org?cc=nobody@mozilla.org&subject=This%20is%20the%20subject</a></li> +</ul> + +<h2 id="小结">小结</h2> + +<p>这就是链接!当您开始查看样式时,您将在稍后的课程中返回链接。接下来是HTML,我们将返回文本语义,并查看一些更高级/不寻常的功能,您会发现有用的-高级文本格式是您的下一站。</p> + +<p>{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals", "Learn/HTML/Introduction_to_HTML/Advanced_text_formatting", "Learn/HTML/Introduction_to_HTML")}}</p> + +<h2 id="本章目录">本章目录</h2> + +<ul> + <li><a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/Getting_started">开始学习 HTML</a></li> + <li><a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML">“头”里有什么?HTML 元信息</a></li> + <li><a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/HTML_text_fundamentals">HTML 文字处理初步</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks">创建超链接</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Advanced_text_formatting">高级文字格式</a></li> + <li><a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/文件和网站结构">文档和站点结构</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Debugging_HTML">HTML 调试</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Marking_up_a_letter">课程测验:为信件排版</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Structuring_a_page_of_content">课程测验:构建内容丰富的网页</a></li> +</ul> diff --git a/files/zh-cn/learn/html/introduction_to_html/debugging_html/index.html b/files/zh-cn/learn/html/introduction_to_html/debugging_html/index.html new file mode 100644 index 0000000000..86ebf29c63 --- /dev/null +++ b/files/zh-cn/learn/html/introduction_to_html/debugging_html/index.html @@ -0,0 +1,179 @@ +--- +title: HTML 调试 +slug: learn/HTML/Introduction_to_HTML/Debugging_HTML +tags: + - Debug + - HTML + - W3C + - 初学者 + - 指南 + - 调试 + - 错误 + - 验证 +translation_of: Learn/HTML/Introduction_to_HTML/Debugging_HTML +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/Document_and_website_structure", "Learn/HTML/Introduction_to_HTML/Marking_up_a_letter", "Learn/HTML/Introduction_to_HTML")}}</div> + +<p class="summary">HTML 优雅明了,但要是出了错,你会不会一头雾水呢,本节将介绍一些查找和修复 HTML 错误的工具。</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">预备知识:</th> + <td>阅读并理解 <a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Getting_started">HTML 入门</a>、<a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals">HTML 文字处理初步</a> 和 <a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks">创建超链接</a> 等文章,熟悉 HTML 的基本概念。</td> + </tr> + <tr> + <th scope="row">学习目标:</th> + <td>学习调试工具的基础用法,以查找 HTML 中的错误。</td> + </tr> + </tbody> +</table> + +<h2 id="调试并不可怕">调试并不可怕</h2> + +<p>写代码通常都是按部就班的,但是一旦犯了错,可怕的代码问题就出现了:或彻底罢工,或得不到正确结果。比如,以下窗口显示了:用 <a href="https://www.rust-lang.org/">Rust</a> 编写的一个小程序在 {{glossary("compile", "编译")}} 时得到的出错信息:</p> + +<p><img alt="一个控制台窗口,显示了一个rust工程编译时的出错信息。(println宏少一个引号)" src="https://mdn.mozillademos.org/files/16527/03.gif" style="display: block; height: 463px; margin: 0px auto; width: 658px;">这里错误信息比较容易理解:"unterminated double quote string",即"双引号字符串未闭合"。错误列表中可以看到 <code>println!(Hello, world!");</code> 这里少一个双引号,然而当程序规模变大时,错误信息也会变得更复杂和更难解释,同时对于 Rust 新手而言,上述提示也是找不到北。</p> + +<p>调试其实没有那么可怕,写代码和调试的关键其实是:熟悉语言本身和相关工具。</p> + +<h2 id="HTML_和调试">HTML 和调试</h2> + +<p>HTML 并不像 Rust 那么难以理解,浏览器并不会将 HTML 编译成其它形式,而是直接解析并显示结果(称之为解释,而非编译)。可以说 HTML 的 {{glossary("element", "元素")}} 语法比 Rust、{{glossary("JavaScript")}} 或 {{glossary("Python")}} 这样“真正的编程语言”更容易理解。浏览器解析 HTML 的过程比编程语言的编译运行的过程要<strong>宽松</strong>得多,但这是一把双刃剑。</p> + +<h3 id="宽松的代码">宽松的代码</h3> + +<p>宽松是什么意思呢?通常写错代码会带来以下两种主要类型的错误:</p> + +<ul> + <li><strong>语法错误</strong>:由于拼写错误导致程序无法运行,就像上面的 Rust 示例。通常熟悉语法并理解错误信息后很容易修复。</li> + <li><strong>逻辑错误:</strong>不存在语法错误,但代码无法按预期运行。通常逻辑错误比语法错误更难修复,因为无法得到指向错误源头的信息。</li> +</ul> + +<p>HTML 本身不容易出现语法错误,因为浏览器是以宽松模式运行的,这意味着即使出现语法错误浏览器依然会继续运行。浏览器通常都有内建规则来解析书写错误的标记,所以即使与预期不符,页面仍可显示出来。当然,是存在隐患的。</p> + +<div class="note"> +<p><strong>注:</strong>HTML 之所以以宽松的方式进行解析,是因为 Web 创建的初心就是:人人可发布内容,不去纠结代码语法。如果 Web 以严格的风格起步,也许就不会像今天这样流行了。</p> +</div> + +<h3 id="主动学习:研究宽容的代码风格">主动学习:研究宽容的代码风格</h3> + +<p>现在来研究 HTML 代码的宽松特性。</p> + +<ol> + <li>首先,下载并保存 <a href="https://github.com/roy-tian/learning-area/blob/master/html/introduction-to-html/debugging-html/debug-example.html">debug-example.html</a>。代码中故意留了一些错误,以便探究(这里的 HTML 标记写成了 <strong>糟糕的格式</strong>,与 <strong>良好的格式</strong> 相反)。</li> + <li>下一步,在浏览器中打开,可以看到:<img alt="一个简单的HTML文档,但其中包含一些常见的HTML错误,比如:未关闭的元素、嵌套混乱的元素、未关闭的属性。" src="https://mdn.mozillademos.org/files/16528/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7_2019-02-22_06.28.07.png" style="display: block; margin: 0px auto;"></li> + <li>看起来糟透了,我们到源代码中寻找原因(只列出 <code>body</code> 部分): + <pre class="brush: html notranslate"><h1>HTML 调试示例</h1> + +<p>什么使得 HTML 出错? + +<ul> + <li>未闭合的元素:如果元素<strong>没有正确的结束标记,那么将影响下方整个区域,这不是你期望的。 + + <li>错误嵌套元素:正确进行嵌套是一项重要的编码习惯。<strong>重点(strong)<em>重点强调(strongly emphasised)?</strong>这又是什么鬼?</em> + + <li>未闭合的属性:另一种 HTML 常见错误。来看一个示例:<a href="https://www.mozilla.org/>Mozilla 主页链接</a> +</ul> +</pre> + </li> + <li>以下是问题清单: + <ul> + <li>{{htmlelement("p","段落(Paragraph)")}} 和 {{htmlelement("li","列表项(list item)")}} 元素没有结束标签。但是由于元素的结束和另一个的开始很容易推断出来,因此上图中并没有太严重的渲染错误。</li> + <li>第一个 {{htmlelement("strong")}} 元素没有结束标签。这就严重了,因为该元素结束的位置难以确定。事实上所有剩余文本都加粗了。</li> + <li>一下嵌套有问题:<code><strong>重点(strong)<em>重点强调(strongly emphasised)?</strong>这又是什么鬼?</em></code>。浏览器很难做出正确解释,理由同上。</li> + <li>{{htmlattrxref("href","a")}} 属性缺少了一个双引号。从而导致了一个最严重的问题:整个链接完全没有渲染出来。</li> + </ul> + </li> + <li>下面暂时忽略源代码中的标记,先看一下浏览器渲染出的标记。打开浏览器的开发者工具。如果不太熟悉,请先阅读 <a href="/zh-CN/docs/Learn/Discover_browser_developer_tools">浏览器开发工具概览</a>。</li> + <li>在 DOM 查看器中可以看到渲染的标记:<img alt="Firefox控制台中的HTML检查器,可标亮元素,(图中标亮了“什么使得HTML出错?”)可以看到浏览器自动补齐了</p>关闭标签" src="https://mdn.mozillademos.org/files/16529/html-inspector.png" style="display: block; height: 1214px; margin: 0px auto; width: 1700px;"></li> + <li>通过 DOM 查看器可以清楚地看到,浏览器已经尝试修补代码错误(我们尝试了 Firefox,其他现代浏览器也应给出同样结果): + <ul> + <li>段落和列表元素加上了关闭标签。</li> + <li>第一个 <code><strong></code> 没有明确的关闭标签,因此浏览器为之后所有独立块都补全了 <code><strong></strong></code>。</li> + <li>浏览器是这样修补嵌套错误的: + <pre class="brush: html notranslate"><strong>重点(strong) + <em>重点强调(strongly emphasised)?</em> +</strong> +<em>这又是什么鬼?</em></pre> + </li> + <li>删除整个缺少双引号的链接。最后一个列表项就成了: + <pre class="brush: html notranslate"><li> + <strong>未闭合的属性:另一种 HTML 常见错误。来看一个示例:</strong> +</li></pre> + </li> + </ul> + </li> +</ol> + +<h3 id="HTML_验证">HTML 验证</h3> + +<p>阅读以上示例后,你发现保持良好 HTML 格式的重要性。那么应该如何做呢?以上示例规模较小,查找错误还不难,但是一个非常庞大、复杂的 HTML 文档呢?</p> + +<p>最好的方法就是让你的HTML页面通过 <a href="https://validator.w3.org/">Markup Validation Service</a>。由 W3C(制定 HTML、CSS 和其他网络技术标准的组织) 创立并维护的标记验证服务。把一个 HTML 文档加载至本网页并运行 ,网页会返回一个错误报告。</p> + +<p><img alt="The HTML validator homepage" src="https://mdn.mozillademos.org/files/12441/validator.png" style="display: block; margin: 0 auto;"></p> + +<p>网页可以接受网址、上传一个 HTML 文档,或者直接输入一些 HTML 代码。</p> + +<h3 id="主动学习:验证_HTML_文档">主动学习:验证 HTML 文档</h3> + +<p>不妨用上文的 <a href="https://github.com/roy-tian/learning-area/blob/master/html/introduction-to-html/debugging-html/debug-example.html">debug-example.html</a> 尝试一下:</p> + +<ol> + <li>在浏览器中打开 <a href="https://validator.w3.org/">Markup Validation Service</a> 。</li> + <li>选择 <a href="https://validator.w3.org/#validate_by_input">Validate by Direct Input</a> 标签。</li> + <li>将整个示例文档的代码(而不仅仅是<code>body</code>部分)复制粘贴到正中的文本框内。</li> + <li><em>点击 </em><strong>Check</strong><em> 按钮。</em></li> +</ol> + +<p>将返回一个包含错误和其它信息的列表。</p> + +<p><img alt="W3C验证工具为本示例给出的验证结果。" src="https://mdn.mozillademos.org/files/16530/validation-result.png" style="display: block; margin: 0px auto;"></p> + +<h4 id="错误信息分析">错误信息分析</h4> + +<p>错误信息一般都是有用的,也有没用的,有一些经验后你就能够分析并修复这些错误。下面来观察这些错误信息。可以看到每条信息都对应一个行号和一条信息,使得定位错误更方便。</p> + +<ul> + <li>End tag <code>li</code> implied, but there were open elements(需要 <code>li</code> 的结束标签,但又开始了新的元素)(共出现 2 次):这条信息表明有开始标签必须有结束标签,必须出现结束标签的地方却没有找到它。行/列信息指出结束标签必须出现的位置的第一行,这一线索已经足够明显了。</li> + <li>Unclosed element <code>strong</code>(未闭合元素 <code>strong</code> ):非常容易理解,{{htmlelement("strong")}} 元素没有闭合,行/列信息表明了它的位置。</li> + <li>End tag <code>strong</code> violates nesting rules(结束标签 <code>strong</code> 违反了嵌套规则):指出了错误嵌套的元素,行/列信息表明了它的位置。</li> + <li>End of file reached when inside an attribute value. Ignoring tag(在属性值内达到文件末尾。忽略标签): 这个比较难懂,它说的是在某个地方有一个属性的值格式有误,估计是在文件末尾附近,因为文件的结尾出现在了一个属性值里。事实上浏览器没有渲染超链接已经是一个很明显的线索了。</li> + <li>End of file seen and there were open elements(文件结尾有未闭合的元素):这个略有歧义,但基本上表明了有元素没有正确闭合。行号指向文件最后几行,且错误信息给出了一个这种错误的案例: + <pre class="notranslate">来看一个示例:<a href="https://www.mozilla.org/>Mozilla 主页链接</a> ↩ </ul>↩ </body>↩</html></pre> + + <div class="note"> + <p><strong>注:</strong>属性缺少结束引号会导致元素无法闭合。因为文档所有剩余部分(直到文档某处出现一个引号)都将被解析为属性的内容。</p> + </div> + </li> + <li>Unclosed element <code>ul</code>(未闭合元素 <code>ul</code>):这个意义不大,因为 {{htmlelement("ul")}} 已经正确闭合了。出现这个错误是因为 {{htmlelement("a")}} 元素没有右引号而没有闭合。</li> +</ul> + +<p><span>如果你不能一次弄懂所有的错误,别着急,可以试试先修复那些已经弄懂的,再申请验证,看看剩下哪些错误。有时候先修复的错误可能让你摆脱后面一系列的错误,因为一个小问题可能引发一连串错误,就像多米诺骨牌。</span></p> + +<p><span>所有错误都修复之后会得到以下输出:</span></p> + +<p><img alt="W3C站点上HTML通过验证的横幅" src="https://mdn.mozillademos.org/files/16531/valid-html-banner.png" style="display: block; height: 96px; margin: 0px auto; width: 996px;"></p> + +<h2 id="小结">小结</h2> + +<p>以上就是 HTML 调试的一篇入门介绍,同时对于调试 CSS 和 JavaScript 也有帮助,或者你职业生涯中的任一门语言。这也是 HTML 学习一章的最后一节,接下来是两个小测试,点击“下一页”来小试牛刀吧。</p> + +<p>{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/Document_and_website_structure", "Learn/HTML/Introduction_to_HTML/Marking_up_a_letter", "Learn/HTML/Introduction_to_HTML")}}</p> + +<h2 id="本章目录">本章目录</h2> + +<ul> + <li><a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/Getting_started">开始学习 HTML</a></li> + <li><a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML">“头”里有什么?HTML 元信息</a></li> + <li><a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/HTML_text_fundamentals">HTML 文字处理初步</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks">创建超链接</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Advanced_text_formatting">高级文字格式</a></li> + <li><a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/文件和网站结构">文档和站点结构</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Debugging_HTML">HTML 调试</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Marking_up_a_letter">课程测验:为信件排版</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Structuring_a_page_of_content">课程测验:构建内容丰富的网页</a></li> +</ul> diff --git a/files/zh-cn/learn/html/introduction_to_html/getting_started/index.html b/files/zh-cn/learn/html/introduction_to_html/getting_started/index.html new file mode 100644 index 0000000000..34fa761a4e --- /dev/null +++ b/files/zh-cn/learn/html/introduction_to_html/getting_started/index.html @@ -0,0 +1,683 @@ +--- +title: 开始学习 HTML +slug: learn/HTML/Introduction_to_HTML/Getting_started +tags: + - HTML + - 元素 + - 属性 + - 指南 +translation_of: Learn/HTML/Introduction_to_HTML/Getting_started +--- +<div>{{LearnSidebar}}</div> + +<div>{{NextMenu("Learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML", "Learn/HTML/Introduction_to_HTML")}}</div> + +<p class="summary">本文将从 HTML 最基础的部分讲起,对元素(Element)、属性(Attribute)以及可能涉及的一些重要术语进行介绍,并明确它们在语言中所处的位置。本文还会讲解 HTML 元素和页面的组织方式,以及其他一些重要的基本语言特性。学习的过程中,我们会使用 HTML 做一些好玩的事情。</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">预备知识:</th> + <td>具备计算机基础知识,安装了<a href="/zh-CN/Learn/Getting_started_with_the_web/Installing_basic_software">基础软件环境</a>,了解基本的<a href="/zh-CN/Learn/Getting_started_with_the_web/Dealing_with_files">文件组织方法</a>。</td> + </tr> + <tr> + <th scope="row">学习目标:</th> + <td>熟悉 HTML 语言的基础知识,掌握几个 HTML 元素的基本用法。</td> + </tr> + </tbody> +</table> + +<h2 id="什么是_HTML">什么是 HTML?</h2> + +<p>{{glossary("HTML")}} (HyperText Markup Language) 不是一门编程语言,而是一种用来告知浏览器如何组织页面的<strong>标记语言</strong>。HTML 可复杂、可简单,一切取决于开发者。它由一系列的<strong>元素({{Glossary("Element", "elements")}})</strong>组成,这些元素可以用来包围不同部分的内容,使其以某种方式呈现或者工作。 一对标签( {{Glossary("Tag", "tags")}})可以为一段文字或者一张图片添加超链接,将文字设置为斜体,改变字号,等等。 例如下面一行内容:</p> + +<pre>我的猫咪脾气爆:)</pre> + +<p>可以将这行文字封装成一个段落(Paragraph){{htmlelement("p")}}元素来使其在单独一行呈现:</p> + +<pre class="brush: html"><p>我的猫咪脾气爆:)</p></pre> + +<div class="note"> +<p><strong>注:</strong>HTML 标签不区分大小写。也就是说,输入标签时既可以使用大写字母也可以使用小写字母。例如,标签 {{htmlelement("title")}} 写作<code><title><font face="x-locale-heading-primary, zillaslab, Palatino, Palatino Linotype, x-locale-heading-secondary, serif"><span style="background-color: #fff3d4;">、</span></font></code><code><TITLE></code>、<code><Title></code>、<code><TiTlE></code>,等等都可以正常工作。不过,从一致性、可读性等各方面来说,最好仅使用小写字母。</p> +</div> + +<h2 id="剖析一个_HTML_元素">剖析一个 HTML 元素</h2> + +<p>让我们进一步探讨我们的段落元素:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/16475/element.png" style="display: block; height: 255px; margin: 0px auto; width: 821px;"></p> + +<p>这个元素的主要部分有:</p> + +<ol> + <li><strong>开始标签</strong>(Opening tag):包含元素的名称(本例为 p),被左、右角括号所包围。表示元素从这里开始或者开始起作用 —— 在本例中即段落由此开始。</li> + <li><strong>结束标签</strong>(Closing tag):与开始标签相似,只是其在元素名之前包含了一个斜杠。这表示着元素的结尾 —— 在本例中即段落在此结束。初学者常常会犯忘记包含结束标签的错误,这可能会产生一些奇怪的结果。</li> + <li><strong>内容</strong>(Content):元素的内容,本例中就是所输入的文本本身。</li> + <li><strong>元素</strong>(Element):开始标签、结束标签与内容相结合,便是一个完整的元素。</li> +</ol> + +<h3 id="主动学习:创建第一个_HTML_元素">主动学习:创建第一个 HTML 元素</h3> + +<p>通过使用标签<code><em></code>和<code></em></code>(在前面放置<code><em></code>打开元素,在后面放置<code></em></code>关闭元素)——这使得行内容变成斜体强调!你可以在“输出”区域中实时查看更改更新。</p> + +<p>如果写错了,可随时按【重置】按钮重新开始,如果实在想不出来,可按【显示答案】按钮查看答案。</p> + +<div class="hidden"> +<h6 id="Playable_code">Playable code</h6> + +<pre class="brush: html"><!DOCTYPE html> +<html lang="zh-CN"> + <head> + <meta charset="utf-8"> + <style> + body { font-family: '微软雅黑', Helvetica, Arial, sans-serif; margin: 10px; background: #f5f9fa; } + h2 { font-size: 16px; } + code, textarea { font-family: Consolas, Menlo, monospace; } + .output { min-height: 50px; } + .input { min-height: 100px; width: 95%; } + .a11y-label { margin: 0; text-align: right; font-size: 0.7rem; width: 98%; } + .controls { width: 96%; text-align: right; } + </style> + </head> + <body> + <h2>实时输出</h2> + <div class="output"></div> + + <h2>可编辑代码</h2> + <p class="a11y-label">按 ESC 退出编辑区域,按 Tab 可插入制表符 <code>'\t'</code> </p> + <textarea id="code" class="input"></textarea> + + <div class="controls"> + <button id="btn-reset">重置</button> + <button id="btn-solution">显示答案</button> + </div> + <script> + const btnReset = document.getElementById('btn-reset'); + const btnSolution = document.getElementById('btn-solution'); + const blockOutput = document.querySelector('.output'); + const blockInput = document.querySelector('.input'); + const original = '刀枪剑戟 斧钺钩叉'; + const answer = '<em>刀枪剑戟 斧钺钩叉</em>'; + let userEntry = ""; + + init(); + btnReset.addEventListener('click', init); + + btnSolution.addEventListener('click', () => { + if (btnSolution.textContent === '显示答案') { + blockInput.value = + blockOutput.innerHTML = answer; + btnSolution.textContent = '隐藏答案'; + } else { + blockInput.value = + blockOutput.innerHTML = userEntry; + btnSolution.textContent = '显示答案'; + } + }); + + blockInput.addEventListener('keydown', (e) => { + switch (e.key) { + case 'Tab': + e.preventDefault(); + insertAtCursor('\t'); + break; + case "Escape": + blockInput.blur(); + break; + } + }); + + blockInput.addEventListener('keyup', () => { + userEntry = blockInput.value; + blockOutput.innerHTML = blockInput.value; + if (btnSolution.textContent === '隐藏答案') { + btnSolution.textContent = '显示答案'; + } + }); + + function init() { + userEntry = + blockOutput.innerHTML = + blockInput.value = original; + btnSolution.textContent = '显示答案'; + } + + function insertAtCursor(text) { + const scrollPos = blockInput.scrollTop; + const cursorPos = blockInput.selectionStart; + + const front = blockInput.value.substring(0, cursorPos); + const back = blockInput.value.substring( + blockInput.selectionEnd, blockInput.value.length); + + blockInput.value = front + text + back; + blockInput.selectionStart = + blockInput.selectionEnd = cursorPos + text.length; + blockInput.focus(); + blockInput.scrollTop = scrollPos; + } + </script> + </body> +</html></pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code', 700, 400, "", "", "hide-codepen-jsfiddle") }}</p> + +<h3 id="嵌套元素">嵌套元素</h3> + +<p>你也可以把元素放到其它元素之中——这被称作嵌套。如果我们想要表明我们的小猫脾气很暴躁,可以将<strong>“爆”</strong>嵌套在{{htmlelement("strong")}} 中,意味着这个单词被着重强调:</p> + +<pre class="brush: html"><p>我的猫咪脾气<strong>爆</strong>:)</p></pre> + +<p>你需要确保元素被正确的嵌套:在上面的例子中我们先打开{{htmlelement("p")}}元素,然后才打开{{htmlelement("strong")}}元素,因此必须先将{{htmlelement("strong")}}元素关闭,然后再去关闭{{htmlelement("p")}}元素。下面的例子是错误的:</p> + +<pre class="example-bad brush: html"><p>我的猫咪脾气<strong>爆:)</p></strong></pre> + +<p>所有的元素都需要正确的打开和关闭,这样才能按你所想的方式展现。如果像上述的例子一样进行了错误的嵌套,那么浏览器会去猜测你想要表达的意思,但很有可能会得出错误的结果。所以永远不要这么做!</p> + +<h3 id="块级元素和内联元素">块级元素和内联元素</h3> + +<p>在HTML中有两种你需要知道的重要元素类别,块级元素和内联元素。</p> + +<ul> + <li>块级元素在页面中以块的形式展现 —— 相对于其前面的内容它会出现在新的一行,其后的内容也会被挤到下一行展现。块级元素通常用于展示页面上结构化的内容,例如段落、列表、导航菜单、页脚等等。一个以block形式展现的块级元素不会被嵌套进内联元素中,但可以嵌套在其它块级元素中。</li> + <li>内联元素通常出现在块级元素中并环绕文档内容的一小部分,而不是一整个段落或者一组内容。内联元素不会导致文本换行:它通常出现在一堆文字之间例如超链接元素{{htmlelement("a")}}或者强调元素{{htmlelement("em")}}和 {{htmlelement("strong")}}。</li> +</ul> + +<p>看一看下面的例子:</p> + +<pre class="brush: html"><em>第一</em><em>第二</em><em>第三</em> + +<p>第四</p><p>第五</p><p>第六</p> +</pre> + +<p>{{htmlelement("em")}} 是一个内联元素,所以就像你在下方可以看到的,第一行代码中的三个元素都没有间隙的展示在了同一行。而{{htmlelement("p")}}是一个块级元素,所以第二行代码中的每个元素分别都另起了新的一行展现,并且每个段落间都有一些间隔(这是因为默认的浏览器有着默认的展示{{htmlelement("p")}}元素的<a href="/en-US/docs/Learn/CSS/Introduction_to_CSS">CSS styling</a>)。</p> + +<p>{{ EmbedLiveSample('块级元素和内联元素', 700, 200, "", "", "hide-codepen-jsfiddle") }}</p> + +<div class="note"> +<p><strong>注</strong>: HTML5重新定义了元素的类别:见 <a href="https://html.spec.whatwg.org/multipage/indices.html#element-content-categories">元素内容分类</a>(<a href="/zh-CN/docs/Web/Guide/HTML/Content_categories">译文</a>)。尽管这些新的定义更精确,但却比上述的 “块级元素” 和 “内联元素” 更难理解,因此在之后的讨论中仍使用旧的定义。</p> +</div> + +<div class="note"> +<p><strong>注</strong>: 在这篇文章中提到的“块”和“内联”,不应该与 <a href="https://developer.mozilla.org/en-US/docs/Learn/CSS/Introduction_to_CSS/Box_model#Types_of_CSS_boxes">the types of CSS boxes</a> 中的同名术语相混淆. 尽管他们默认是相关的,但改变CSS显示类型并不会改变元素的分类,也不会影响它可以包含和被包含于哪些元素。防止这种混淆也是HTML5摒弃这些术语的原因之一。</p> +</div> + +<div class="note"> +<p><strong>注</strong>: 你可以查阅包含了块级元素和内联元素列表的参考页面—see <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements">Block-level elements</a> and <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Inline_elements">Inline elements</a>.</p> +</div> + +<h3 id="空元素">空元素</h3> + +<p>不是所有元素都拥有开始标签,内容,结束标签。一些元素只有一个标签,通常用来在此元素所在位置插入/嵌入一些东西。例如:元素{{htmlelement("img")}}是用来在元素{{htmlelement("img")}}所在位置插入一张指定的图片。例子如下:</p> + +<pre class="brush: html"><img src="https://roy-tian.github.io/learning-area/extras/getting-started-web/beginner-html-site/images/firefox-icon.png"></pre> + +<p>显示如下:</p> + +<p>{{ EmbedLiveSample('空元素', 700, 300, "", "", "hide-codepen-jsfiddle") }}</p> + +<div class="note"> +<p><strong>注</strong>: 空元素(Empty elements) 有时也被叫作 <em>void elements</em>.</p> +</div> + +<h2 id="属性">属性</h2> + +<p>元素也可以拥有属性,如下:</p> + +<p><img alt='&amp;amp;lt;p class="editor-note">我的猫咪脾气爆&amp;amp;lt;/p>' src="https://mdn.mozillademos.org/files/16476/attribute.png" style="display: block; margin: 0px auto;"></p> + +<p>属性包含元素的额外信息,这些信息不会出现在实际的内容中。在上述例子中,这个class属性给元素赋了一个识别的名字(id),这个名字此后可以被用来识别此元素的样式信息和其他信息。</p> + +<p>一个属性必须包含如下内容:</p> + +<ol> + <li>一个空格,在属性和元素名称之间。(如果已经有一个或多个属性,就与前一个属性之间有一个空格。)</li> + <li>属性名称,后面跟着一个等于号。</li> + <li>一个属性值,由一对引号“ ”引起来。</li> +</ol> + +<h3 id="学习实践:为一个元素添加属性">学习实践:为一个元素添加属性</h3> + +<p>另一个例子是关于元素{{htmlelement("a")}}的——元素{{htmlelement("a")}}是锚,它使被标签包裹的内容成为一个超链接。此元素也可以添加大量的属性,其中几个如下:</p> + +<ul> + <li><code>href</code>: 这个属性声明超链接的web地址,当这个链接被点击浏览器会跳转至href声明的web地址。例如:<code>href="https://www.mozilla.org/"</code>。</li> + <li><code>title</code>: 标题<code>title</code>属性为超链接声明额外的信息,比如你将链接至的那个页面。例如:<code>title="The Mozilla homepage"</code>。当鼠标悬停在超链接上面时,这部分信息将以工具提示的形式显示。</li> + <li><code>target</code>: 目标<code>target</code>属性用于指定链接如何呈现出来。例如,<code>target="_blank"</code>将在新标签页中显示链接。如果你希望在当前标签页显示链接,忽略这个属性即可。</li> +</ul> + +<p>编辑下面的文本框中的内容,使之变成指向任一个你喜欢的web地址的链接。首先,添加<a>元素,然后为它添加href属性和title属性。你可以即时的在输出区域看到你修改的内容。你应该可以看到一个连接,当鼠标移上此链接时会显示title属性值,当点击此链接时会跳转到href指定的web地址。记住:在元素名和属性名之间以及两个属性之间要有一个空格。</p> + +<p>如果写错了,可随时按【重置】按钮重新开始,如果实在想不出来,可按【显示答案】按钮查看答案。</p> + +<div class="hidden"> +<h6 id="Playable_code2">Playable code2</h6> + +<pre class="brush: html"><!DOCTYPE html> +<html lang="zh-CN"> + <head> + <meta charset="utf-8"> + <style> + body { font-family: '微软雅黑', Helvetica, Arial, sans-serif; margin: 10px; background: #f5f9fa; } + h2 { font-size: 16px; } + code, textarea { font-family: Consolas, Menlo, monospace; } + .output { min-height: 50px; } + .input { min-height: 100px; width: 95%; } + .a11y-label { margin: 0; text-align: right; font-size: 0.7rem; width: 98%; } + .controls { width: 96%; text-align: right; } + </style> + + </head> + <body> + <h2>实时输出</h2> + <div class="output"></div> + + <h2>可编辑代码</h2> + <p class="a11y-label">按 ESC 退出编辑区域,按 Tab 可插入制表符 <code>'\t'</code> </p> + <textarea id="code" class="input"></textarea> + + <div class="controls"> + <button id="btn-reset">重置</button> + <button id="btn-solution">显示答案</button> + </div> + <script> + const btnReset = document.getElementById('btn-reset'); + const btnSolution = document.getElementById('btn-solution'); + const blockOutput = document.querySelector('.output'); + const blockInput = document.querySelector('.input'); + const original = '<p>欲练葵花宝典,需引刀自宫</p>'; + const answer = '<p>欲练<a href="https://zh.wikipedia.org/zh-hans/葵花宝典" title="葵花宝典简介" target="_blank">葵花宝典</a>,需引刀自宫</p>'; + let userEntry = ""; + + init(); + btnReset.addEventListener('click', init); + + btnSolution.addEventListener('click', () => { + if (btnSolution.textContent === '显示答案') { + blockInput.value = + blockOutput.innerHTML = answer; + btnSolution.textContent = '隐藏答案'; + } else { + blockInput.value = + blockOutput.innerHTML = userEntry; + btnSolution.textContent = '显示答案'; + } + }); + + blockInput.addEventListener('keydown', (e) => { + switch (e.key) { + case 'Tab': + e.preventDefault(); + insertAtCursor('\t'); + break; + case "Escape": + blockInput.blur(); + break; + } + }); + + blockInput.addEventListener('keyup', () => { + userEntry = blockInput.value; + blockOutput.innerHTML = blockInput.value; + if (btnSolution.textContent === '隐藏答案') { + btnSolution.textContent = '显示答案'; + } + }); + + function init() { + userEntry = + blockOutput.innerHTML = + blockInput.value = original; + btnSolution.textContent = '显示答案'; + } + + function insertAtCursor(text) { + const scrollPos = blockInput.scrollTop; + const cursorPos = blockInput.selectionStart; + + const front = blockInput.value.substring(0, cursorPos); + const back = blockInput.value.substring( + blockInput.selectionEnd, blockInput.value.length); + + blockInput.value = front + text + back; + blockInput.selectionStart = + blockInput.selectionEnd = cursorPos + text.length; + blockInput.focus(); + blockInput.scrollTop = scrollPos; + } + </script> + </body> +</html> +</pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code2', 700, 350, "", "", "hide-codepen-jsfiddle") }}</p> + +<div class="blockIndicator note"> +<p><strong>译注:</strong>可到 Github 在线使用这个“<a class="external external-icon" href="https://roy-tian.github.io/learning-area/extras/tools/playable-code">代码操场</a>”。</p> +</div> + +<h3 id="布尔属性">布尔属性</h3> + +<p>有时你会看到没有值的属性,它是合法的。这些属性被称为布尔属性,他们只能有跟它的属性名一样的属性值。例如{{htmlattrxref("disabled", "input")}} 属性,他们可以标记表单输入使之变为不可用(变灰色),此时用户不能向他们输入任何数据。</p> + +<pre><input type="text" disabled="disabled"></pre> + +<p>方便起见,我们完全可以将其写成以下形式(我们还提供了一个非禁止输入的表单元素供您参考,以作为对比):</p> + +<pre class="brush: html"><!-- 使用disabled属性来防止终端用户输入文本到输入框中 --> +<input type="text" disabled> + +<!-- 下面这个输入框没有disabled属性,所以用户可以向其中输入 --> +<input type="text"> +</pre> + +<p>上面两段HTML代码产生的效果如下:</p> + +<p>{{ EmbedLiveSample('布尔属性', 700, 100, "", "", "hide-codepen-jsfiddle") }}</p> + +<h3 id="省略包围属性值的引号">省略包围属性值的引号</h3> + +<p>当你浏览那些粗糙的web网站,你将会看见各种各样奇怪的标记风格,其中就有不给属性值添加引号。在某些情况下它是被允许的,但是其他情况下会破坏你的标记。例如,我们可以写一个只拥有一个href属性的链接,如下:</p> + +<pre class="example-bad brush: html"><a href=<code>https://www.mozilla.org/</code>>收藏页面</a></pre> + +<p>然而,当我们再添加一个title属性时就会出错,如下:</p> + +<pre class="example-bad brush: html"><a href=<code>https://www.mozilla.org/</code> title=The Mozilla homepage>收藏页面</a></pre> + +<p>此时浏览器会误解你的标记,它会把title属性理解为三个属性——title的属性值为"The“,另外还有两个布尔属性“<code>Mozilla</code>”和“<code>homepage</code>”。看下面的例子,它明显不是我们所期望的,并且在这个编码里面它会报错或者出现异常行为。试一试把鼠标移动到链接上,看会显示什么title属性值!</p> + +<p>{{ EmbedLiveSample('省略包围属性值的引号', 700, 100, "", "", "hide-codepen-jsfiddle") }}</p> + +<p>我们建议始终添加引号——这样可以避免很多问题,并且使代码更易读。</p> + +<h3 id="单引号或者双引号?">单引号或者双引号?</h3> + +<p>在目前为止,本章内容所有的属性都是由双引号来包裹。也许在一些HTML中,你以前也见过单引号。这只是风格的问题,你可以从中选择一个你喜欢的。以下两种情况都可以:</p> + +<pre class="brush: html"><a href="http://www.example.com">示例站点链接</a> + +<a href='http://www.example.com'>示例站点链接</a></pre> + +<p>但你应该注意单引号和双引号不能在一个属性值里面混用。下面的语法是错误的:</p> + +<pre class="example-bad brush: html"><a href="http://www.example.com'>示例站点链接</a></pre> + +<p>在一个HTML中已使用一种引号,你可以在此引号中嵌套另外一种引号:</p> + +<pre class="brush: html"><a href="http://www.example.com" title="你觉得'好玩吗'?">示例站点链接</a></pre> + +<p>如果你想将引号当作文本显示在html中,你就必须使用<a href="#实体引用:_在HTML中包含特殊字符">实体引用</a>。</p> + +<h2 id="剖析HTML文档">剖析HTML文档</h2> + +<p>学习了一些HTML元素的基础知识,这些元素单独一个是没有意义的。现在我们来学习这些特定元素是怎么被结合起来,从而形成一个完整的HTML页面的:</p> + +<pre class="brush: html"><!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>我的测试站点</title> + </head> + <body> + <p>这是我的页面</p> + </body> +</html></pre> + +<p>分析如下:</p> + +<ol> + <li><code><!DOCTYPE html></code>: 声明文档类型. 很久以前,早期的HTML(大约1991年2月),文档类型声明类似于链接,规定了HTML页面必须遵从的良好规则,能自动检测错误和其他有用的东西。使用如下: + + <pre><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" +"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"></pre> + 然而这种写法已经过时了,这些内容已成为历史。只需要知道 <code><!DOCTYPE html></code> 是最短有效的文档声明。</li> + <li><code><html></html></code>: <code><html></code>元素。这个元素包裹了整个完整的页面,是一个根元素。</li> + <li><code><head></head></code>: <code><head>元素</code>. 这个元素是一个容器,它包含了所有你想包含在HTML页面中但不想在HTML页面中显示的内容。这些内容包括你想在搜索结果中出现的关键字和页面描述,CSS样式,字符集声明等等。以后的章节能学到更多关于<head>元素的内容。</li> + <li><code><meta charset="utf-8"></code>: 这个元素设置文档使用utf-8字符集编码,utf-8字符集包含了人类大部分的文字。基本上他能识别你放上去的所有文本内容。毫无疑问要使用它,并且它能在以后避免很多其他问题。</li> + <li><code><title></title></code>: 设置页面标题,出现在浏览器标签上,当你标记/收藏页面时它可用来描述页面。</li> + <li><code><body></body></code>: <code><body></code>元素。 包含了你访问页面时所有显示在页面上的内容,文本,图片,音频,游戏等等。</li> +</ol> + +<h3 id="学习实践:为HTML文档添加一些特征">学习实践:为HTML文档添加一些特征</h3> + +<p>如果你想在你的本地练习写一些HTML页面,你可以这样做:</p> + +<ol> + <li>复制上面的HTML页面例子。</li> + <li>在编辑器创建一个新文件。</li> + <li>粘贴代码到这个文件。</li> + <li>保存为<code>index.html</code>.</li> +</ol> + +<div class="note"> +<p><strong>注:</strong>可在 <a href="https://github.com/roy-tian/learning-area/blob/master/html/introduction-to-html/getting-started/index.html">学习区代码仓库</a> 上查看该示例。</p> +</div> + +<p>你可以打开浏览器看看这段代码的效果是什么样的,然后改变代码刷新浏览器看看新的结果。最开始的代码是这样的效果:</p> + +<p><img alt="A simple HTML page that says This is my page" src="https://mdn.mozillademos.org/files/12279/template-screenshot.png" style="display: block; height: 365px; margin: 0px auto; width: 595px;">所以在这段练习中, 你可以用你的电脑在本地编写运行代码,如上所述, 你也可以在下面的简单可编辑窗口编辑它 (此时这个简单的可编辑窗口仅显示<body>标签内的内容.) 我们希望你能够实践以下步骤:</p> + +<ul> + <li>就在{{htmlelement("body")}} 元素开始标签下方,为这个文档添加一个主标题。这个主标题应该被包含在<code><h1></code>开始标签和<code></h1></code>结束标签之间。</li> + <li>编辑这个段落以包含一些你感兴趣的文本。</li> + <li>把字词包含在开始标记<code><strong></code>和结束标记<code></strong></code>之间可以使他们以粗体显示,从而突出任何重要的字词。</li> + <li>在你的文档中添加一个超文本链接,<a href="https://developer.mozilla.org/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Getting_started#%E5%AD%A6%E4%B9%A0%E5%AE%9E%E8%B7%B5%EF%BC%9A%E4%B8%BA%E4%B8%80%E4%B8%AA%E5%85%83%E7%B4%A0%E6%B7%BB%E5%8A%A0%E5%B1%9E%E6%80%A7">如前所述</a>。</li> + <li>在段落下方向你的文档添加一张图片,<a href="https://developer.mozilla.org/zh-CN/docs/learn/HTML/Introduction_to_HTML/Getting_started#%E7%A9%BA%E5%85%83%E7%B4%A0">如前所述</a>。如果你尝试对不同的图片(在你的本地电脑或是在Web的其他位置上)添加链接,那你就更棒了。</li> +</ul> + +<p>如果写错了,可随时按【重置】按钮重新开始,如果实在想不出来,可按【显示答案】按钮查看答案。</p> + +<div class="hidden"> +<h6 id="Playable_code3">Playable code3</h6> + +<pre class="brush: html"><!DOCTYPE html> +<html lang="zh-CN"> + <head> + <meta charset="utf-8"> + <style> + body { font-family: '微软雅黑', Helvetica, Arial, sans-serif; margin: 10px; background: #f5f9fa; } + h2 { font-size: 16px; } + code, textarea { font-family: Consolas, Menlo, monospace; } + .output { min-height: 50px; } + .input { min-height: 100px; width: 95%; } + .a11y-label { margin: 0; text-align: right; font-size: 0.7rem; width: 98%; } + .controls { width: 96%; text-align: right; } + </style> + + </head> + <body> + <h2>实时输出</h2> + <div class="output"></div> + + <h2>可编辑代码</h2> + <p class="a11y-label">按 ESC 退出编辑区域,按 Tab 可插入制表符 <code>'\t'</code> </p> + <textarea id="code" class="input"></textarea> + + <div class="controls"> + <button id="btn-reset">重置</button> + <button id="btn-solution">显示答案</button> + </div> + <script> + const btnReset = document.getElementById('btn-reset'); + const btnSolution = document.getElementById('btn-solution'); + const blockOutput = document.querySelector('.output'); + const blockInput = document.querySelector('.input'); + const original = '<p>相思无用,惟别而已。别期若有定,千般煎熬又何如?莫道黯然销魂,何处柳暗花明?</p>'; + const answer = +`<h1>经典回忆</h1> +<p> + 相思无用,惟别而已。别期若有定,千般煎熬又何如?莫道黯然销魂,何处<strong>柳暗花明</strong>?<br> + ——《<a href="https://zh.wikipedia.org/zh-hans/神鵰俠侶">神雕侠侣</a>》 +</p> +<img src="https://roy-tian.github.io/learning-area/extras/tools/playable-code/images/sdxl.jfif">`; + let userEntry = ""; + + init(); + btnReset.addEventListener('click', init); + + btnSolution.addEventListener('click', () => { + if (btnSolution.textContent === '显示答案') { + blockInput.value = + blockOutput.innerHTML = answer; + btnSolution.textContent = '隐藏答案'; + } else { + blockInput.value = + blockOutput.innerHTML = userEntry; + btnSolution.textContent = '显示答案'; + } + }); + + blockInput.addEventListener('keydown', (e) => { + switch (e.key) { + case 'Tab': + e.preventDefault(); + insertAtCursor('\t'); + break; + case "Escape": + blockInput.blur(); + break; + } + }); + + blockInput.addEventListener('keyup', () => { + userEntry = blockInput.value; + blockOutput.innerHTML = blockInput.value; + if (btnSolution.textContent === '隐藏答案') { + btnSolution.textContent = '显示答案'; + } + }); + + function init() { + userEntry = + blockOutput.innerHTML = + blockInput.value = original; + btnSolution.textContent = '显示答案'; + } + + function insertAtCursor(text) { + const scrollPos = blockInput.scrollTop; + const cursorPos = blockInput.selectionStart; + + const front = blockInput.value.substring(0, cursorPos); + const back = blockInput.value.substring( + blockInput.selectionEnd, blockInput.value.length); + + blockInput.value = front + text + back; + blockInput.selectionStart = + blockInput.selectionEnd = cursorPos + text.length; + blockInput.focus(); + blockInput.scrollTop = scrollPos; + } + </script> + </body> +</html> + +</pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code3', 700, 600,"", "", "hide-codepen-jsfiddle")}}</p> + +<h3 id="HTML中的空白">HTML中的空白</h3> + +<p>在上面的例子中,你可能已经注意到了在代码中包含了很多的空格——这是没有必要的;下面的两个代码片段是等价的:</p> + +<pre class="brush: html"><p>狗 狗 很 呆 萌。</p> + +<p>狗 狗 很 + 呆 萌。</p></pre> + +<p>无论你在HTML元素的内容中使用多少空格(包括空白字符,包括换行),当渲染这些代码的时候,HTML解释器会将连续出现的空白字符减少为一个单独的空格符。</p> + +<p>那么为什么我们会在HTML元素的嵌套中使用那么多的空白呢? 答案就是为了可读性 —— 如果你的代码被很好地进行格式化,那么就很容易理解你的代码是怎么回事,反之就只有聚做一团的混乱.。在我们的HTML代码中,我们让每一个嵌套的元素以两个空格缩进。 你使用什么风格来格式化你的代码取决于你 (比如所对于每层缩进使用多少个空格),但是你应该坚持使用某种风格。</p> + +<h2 id="实体引用:_在HTML中包含特殊字符">实体引用: 在HTML中包含特殊字符</h2> + +<p>在HTML中,字符 <code><</code>, <code>></code>,<code>"</code>,<code>'</code> 和 <code>&</code> 是特殊字符. 它们是HTML语法自身的一部分, 那么你如何将这些字符包含进你的文本中呢, 比如说如果你真的想要在文本中使用符号&或者小于号, 而不想让它们被浏览器视为代码并被解释?</p> + +<p>我们必须使用字符引用 —— 表示字符的特殊编码, 它们可以在那些情况下使用. 每个字符引用以符号&开始, 以分号(;)结束.</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">原义字符</th> + <th scope="col">等价字符引用</th> + </tr> + </thead> + <tbody> + <tr> + <td><</td> + <td>&lt;</td> + </tr> + <tr> + <td>></td> + <td>&gt;</td> + </tr> + <tr> + <td>"</td> + <td>&quot;</td> + </tr> + <tr> + <td>'</td> + <td>&apos;</td> + </tr> + <tr> + <td>&</td> + <td>&amp;</td> + </tr> + </tbody> +</table> + +<p>在下面的例子中你可以看到两个段落,它们在谈论web技术:</p> + +<pre class="brush: html"><p>HTML 中用 <p> 来定义段落元素。</p> + +<p>HTML 中用 &lt;p&gt; 来定义段落元素</p></pre> + +<p>在下面的实时输出中,你会看到第一段是错误的,因为浏览器会认为第二个<p>是开始一个新的段落! 第二段是正确的,因为我们用字符引用来代替了角括号('<'和'>'符号).</p> + +<p>{{ EmbedLiveSample('实体引用:_在HTML中包含特殊字符', 700, 200, "", "", "hide-codepen-jsfiddle") }}</p> + +<div class="note"> +<p><strong>提示</strong>: 维基百科上有一个包含所有可用HTML字符实体引用的列表:<a href="http://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references">XML和HTML字符实体引用列表</a>。</p> +</div> + +<h2 id="HTML注释">HTML注释</h2> + +<p>如同大部分的编程语言一样,在HTML中有一种可用的机制来在代码中书写注释 —— 注释是被浏览器忽略的,而且是对用户不可见的,它们的目的是允许你描述你的代码是如何工作的和不同部分的代码做了什么等等。 如果你在半年后重新返回你的代码库,而且不能记起你所做的事情 —— 或者当你处理别人的代码的时候, 那么注释是很有用的.</p> + +<p>为了将一段HTML中的内容置为注释,你需要将其用特殊的记号<!--和-->包括起来, 比如:</p> + +<pre class="brush: html"><p>我在注释外!</p> + +<!-- <p>我在注释内!</p> --></pre> + +<p>正如你下面所见的那样,第一段出现在了实时输出中,但是第二段却没有。</p> + +<p>{{ EmbedLiveSample('HTML注释', 700, 100,"", "", "hide-codepen-jsfiddle") }}</p> + +<h2 id="总结">总结</h2> + +<p>你已经来到了这篇文章的结尾 —— 希望你享受你的基础的HTML学习的旅程。 在这里你应该可以理解HTML语言的全貌, 它在基础的级别是如何工作,而且可以使用一些元素和属性。 在这个模块的后续文章中,我们会深入一些你已经见过的东西的细节,并且介绍一些新的HTML的特性。未完待续!</p> + +<div class="note"> +<p><strong>提示</strong>: 现在,你将开始学习更多关于HTML的知识,你可能也想了解一些层叠样式列表(<a href="https://developer.mozilla.org/zh-CN/docs/Learn/CSS">CSS</a>)的基础知识。CSS是一种用来设计网页样式的语言(比如,用它改变字体、颜色或页面布局等)。你很快就会发现,HTML和CSS能很好地协调配合。</p> +</div> + +<div>{{NextMenu("Learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML", "Learn/HTML/Introduction_to_HTML")}}</div> + +<h2 id="本章目录">本章目录</h2> + +<ul> + <li><a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/Getting_started">开始学习 HTML</a></li> + <li><a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML">“头”里有什么?HTML 元信息</a></li> + <li><a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/HTML_text_fundamentals">HTML 文字处理初步</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks">创建超链接</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Advanced_text_formatting">高级文字格式</a></li> + <li><a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/文件和网站结构">文档和站点结构</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Debugging_HTML">HTML 调试</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Marking_up_a_letter">课程测验:为信件排版</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Structuring_a_page_of_content">课程测验:构建内容丰富的网页</a></li> +</ul> diff --git a/files/zh-cn/learn/html/introduction_to_html/html_text_fundamentals/index.html b/files/zh-cn/learn/html/introduction_to_html/html_text_fundamentals/index.html new file mode 100644 index 0000000000..39547cae31 --- /dev/null +++ b/files/zh-cn/learn/html/introduction_to_html/html_text_fundamentals/index.html @@ -0,0 +1,915 @@ +--- +title: HTML 文字处理基础 +slug: learn/HTML/Introduction_to_HTML/HTML_text_fundamentals +tags: + - HTML指南 + - 学习 +translation_of: Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML", "Learn/HTML/Introduction_to_HTML/Creating_hyperlinks", "Learn/HTML/Introduction_to_HTML")}}</div> + +<p class="summary">HTML的主要工作是编辑文本结构和文本内容(也称为语义{{glossary("semantics")}}),以便浏览器能正确的显示。 本文介绍了 {{glossary("HTML")}}的使用方法:在一段文本中添加标题和段落,强调语句,创建列表等等。</p> + +<table class="learn-box standard-table" style="height: 161px; width: 663px;"> + <tbody> + <tr> + <th scope="row">先决条件:</th> + <td>阅读 <a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Getting_started">开始学习 HTML</a>,了解基本的 HTML 知识。</td> + </tr> + <tr> + <th scope="row">目的:</th> + <td>学习如何用标记(段落、标题、列表、强调、引用)来建立基础文本页面的文本结构和文本内容。</td> + </tr> + </tbody> +</table> + +<h2 id="基础_标题和段落">基础: 标题和段落</h2> + +<p>大部分的文本结构由标题和段落组成。 不管是小说、报刊、教科书还是杂志等。</p> + +<p><img alt="An example of a newspaper front cover, showing use of a top level heading, subheadings and paragraphs." src="https://mdn.mozillademos.org/files/16552/peoples.jpg" style="display: block; height: 493px; margin: 0px auto; width: 622px;" title="An example of a newspaper front cover, showing use of a top level heading, subheadings and paragraphs."></p> + +<p>内容结构化会使读者的阅读体验更轻松,更愉快。</p> + +<p>在HTML中,每个段落是通过 {{htmlelement("p")}} 元素标签进行定义的, 比如下面这样:</p> + +<pre class="brush: html notranslate"><p>我是一个段落,千真万确。</p></pre> + +<p>每个标题(Heading)是通过“标题标签”进行定义的:</p> + +<pre class="brush: html notranslate"><h1>我是文章的标题</h1></pre> + +<p>这里有六个标题元素标签 —— <code><h1></code>、<code><h2></code>、<code><h3></code>、<code><h4></code>、<code><h5></code>、<code><h6></code>。每个元素代表文档中不同级别的内容; <code><h1></code> 表示主标题(the main heading),<code><h2></code> 表示二级子标题(subheadings),<code><h3></code> 表示三级子标题(sub-subheadings),等等。</p> + +<h3 id="编辑结构层次">编辑结构层次</h3> + +<p>这里举一个例子。在一个故事中,<h1>表示故事的名字,<h2>表示每个章节的标题, <h3>表示每个章节下的子标题,以此类推。</p> + +<pre class="brush: html notranslate"><h1>三国演义</h1> + +<p>罗贯中</p> + +<h2>第一回 宴桃园豪杰三结义 斩黄巾英雄首立功</h2> + +<p>话说天下大势,分久必合,合久必分。周末七国分争,并入于秦。及秦灭之后,楚、汉分争,又并入于汉……</p> + +<h2>第二回 张翼德怒鞭督邮 何国舅谋诛宦竖</h2> + +<p>且说董卓字仲颖,陇西临洮人也,官拜河东太守,自来骄傲。当日怠慢了玄德,张飞性发,便欲杀之……</p> + +<h3>却说张飞</h3> + +<p>却说张飞饮了数杯闷酒,乘马从馆驿前过,见五六十个老人,皆在门前痛哭。飞问其故,众老人答曰:“督邮逼勒县吏,欲害刘公;我等皆来苦告,不得放入,反遭把门人赶打!”……</p></pre> + +<p>所涉及的元素具体代表什么,完全取决于作者编辑的内容,只要层次结构是合理的。在创建此类结构时,您只需要记住一些最佳实践:</p> + +<ul> + <li>您应该最好只对每个页面使用一次<h1> — 这是顶级标题,所有其他标题位于层次结构中的下方。</li> + <li>请确保在层次结构中以正确的顺序使用标题。不要使用<h3>来表示副标题,后面跟<h2>来表示副副标题 - 这是没有意义的,会导致奇怪的结果。</li> + <li>在可用的六个标题级别中,您应该只在每页使用不超过三个,除非您认为有必要使用更多。具有许多级别的文档(即,较深的标题层次结构)变得难以操作并且难以导航。在这种情况下,如果可能,建议将内容分散在多个页面上。</li> +</ul> + +<h3 id="为什么我们需要结构化">为什么我们需要结构化?</h3> + +<p>回答这个问题前,让我们先来看一段文档示例“<a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/html-text-formatting/text-start.html">text-start.html</a>” — 并从运行这段文档示例(美味的豆沙食谱)开始。首先,您可以复制一份并保存到本地机器上,在之后的练习中您将用到它。在这个文档的主体 (body)中包含了多个内容 — 这些内容没有做任何标记,但是编辑时使用了换行 (输入回车/换行跳转到下一行)处理。</p> + +<p>然而,当您在浏览器中打开文档时,您会看到文本显示为一整块!</p> + +<p><img alt="A webpage that shows a wall of unformatted text, because there are no elements on the page to structure it." src="https://mdn.mozillademos.org/files/12972/text-no-formatting.png" style="display: block; height: 420px; margin: 0px auto; width: 594px;"></p> + +<p>这是因为没有元素给内容结构,所以浏览器不知道什么是标题,什么是段落。此外:</p> + +<ul> + <li>用户在阅读网页时,往往会快速浏览以查找相关内容,经常只是阅读开头的标题(我们通常在一个网页上会花费很少的时间 <a class="external external-icon" href="http://www.nngroup.com/articles/how-long-do-users-stay-on-web-pages/">spend a very short time on a web page</a>)。如果用户不能在几秒内看到一些有用的内容,他们很可能会感到沮丧并离开。</li> + <li>对您的网页建立索引的搜索引擎将标题的内容视为影响网页搜索排名的重要关键字。没有标题,您的网页在{{glossary("SEO")}}(搜索引擎优化)方面效果不佳。</li> + <li>严重视力障碍者通常不会阅读网页;他们用听力来代替。完成这项工作的软件叫做屏幕阅读器(<a class="external external-icon" href="http://en.wikipedia.org/wiki/Screen_reader" title="screen readers">screen reader</a>)。该软件提供了快速访问给定文本内容的方法。在使用的各种技术中,它们通过朗读标题来提供文档的概述,让用户能快速找到他们需要的信息。如果标题不可用,用户将被迫听到整个文档的大声朗读。</li> + <li>使用{{glossary("CSS")}}样式化内容,或者使用{{glossary("JavaScript")}}做一些有趣的事情,你需要包含相关内容的元素,所以CSS / JavaScript可以有效地定位它。</li> +</ul> + +<p>因此,我们需要给我们的内容结构标记。</p> + +<h3 id="实践操作_编辑我们的内容结构">实践操作: 编辑我们的内容结构</h3> + +<p>让我们直接跳进一个实例。在下面的示例中,向“Input”字段中的原始文本添加元素,使其在“Output”字段中显示为标题和两个段落。</p> + +<p>如果您犯了错误,您可以使用<em>重置</em>按钮进行重置。如果卡住,请按<em>显示解决方案</em>按钮以查看答案。</p> + +<div class="hidden"> +<h6 id="Playable_code">Playable code</h6> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html lang="zh-CN"> + <head> + <meta charset="utf-8"> + <style> + body { font-family: '微软雅黑', Helvetica, Arial, sans-serif; margin: 10px; background: #f5f9fa; } + h2 { font-size: 16px; } + code, textarea { font-family: Consolas, Menlo, monospace; } + .output { min-height: 200px; } + .input { min-height: 100px; width: 95%; } + .a11y-label { margin: 0; text-align: right; font-size: 0.7rem; width: 98%; } + .controls { width: 96%; text-align: right; } + </style> + + </head> + <body> + <h2>实时输出</h2> + <div class="output"></div> + + <h2>可编辑代码</h2> + <p class="a11y-label">按 ESC 退出编辑区域,按 Tab 可插入制表符 <code>'\t'</code> </p> + <textarea id="code" class="input"></textarea> + + <div class="controls"> + <button id="btn-reset">重置</button> + <button id="btn-solution">显示答案</button> + </div> + <script> + const btnReset = document.getElementById('btn-reset'); + const btnSolution = document.getElementById('btn-solution'); + const blockOutput = document.querySelector('.output'); + const blockInput = document.querySelector('.input'); + const original = '静夜思 床前明月光 疑是地上霜 举头望明月 低头思故乡'; + const answer = +`<h1>静夜思</h1> +<p>床前明月光 疑是地上霜</p> +<p>举头望明月 低头思故乡</p>`; + let userEntry = ""; + + init(); + btnReset.addEventListener('click', init); + + btnSolution.addEventListener('click', () => { + if (btnSolution.textContent === '显示答案') { + blockInput.value = + blockOutput.innerHTML = answer; + btnSolution.textContent = '隐藏答案'; + } else { + blockInput.value = + blockOutput.innerHTML = userEntry; + btnSolution.textContent = '显示答案'; + } + }); + + blockInput.addEventListener('keydown', (e) => { + switch (e.key) { + case 'Tab': + e.preventDefault(); + insertAtCursor('\t'); + break; + case "Escape": + blockInput.blur(); + break; + } + }); + + blockInput.addEventListener('keyup', () => { + userEntry = blockInput.value; + blockOutput.innerHTML = blockInput.value; + if (btnSolution.textContent === '隐藏答案') { + btnSolution.textContent = '显示答案'; + } + }); + + function init() { + userEntry = + blockOutput.innerHTML = + blockInput.value = original; + btnSolution.textContent = '显示答案'; + } + + function insertAtCursor(text) { + const scrollPos = blockInput.scrollTop; + const cursorPos = blockInput.selectionStart; + + const front = blockInput.value.substring(0, cursorPos); + const back = blockInput.value.substring( + blockInput.selectionEnd, blockInput.value.length); + + blockInput.value = front + text + back; + blockInput.selectionStart = + blockInput.selectionEnd = cursorPos + text.length; + blockInput.focus(); + blockInput.scrollTop = scrollPos; + } + </script> + </body> +</html> +</pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code', 700, 500, "", "", "hide-codepen-jsfiddle") }}</p> + +<h3 id="为什么我们需要语义?">为什么我们需要语义?</h3> + +<p>在我们身边的任何地方都要依赖语义学 — 我们依靠以前的经验就知道日常事物都代表什么;当我们看到什么,我们就会知道它代表什么。举个例子, 我们知道红色交通灯表示“停止”,绿色交通灯表示”通行“。 如果运用了错误的语义,事情会迅速地变得非常棘手 (难道有某个国家使用红色代表通行?我不希望如此)</p> + +<p>同样的道理,我们需要确保使用了正确的元素来给予内容正确的意思、作用以及外形。在这里,{{htmlelement("h1")}} 元素也是一个语义元素,<span class="short_text" id="result_box" lang="zh-CN"><span>它给出了包裹在您的页面上用来表示顶级标题的角色(或意义)的文本</span></span>。</p> + +<pre class="brush: html notranslate"><h1>这是一个顶级标题</h1></pre> + +<p>一般来说,浏览器会给它一个更大的字形来让它看上去像个标题(虽然你可以使用CSS让它变成任何你想要的样式。更重要的是,它的语义值将以多种方式被使用,比如通过搜索引擎和屏幕阅读器(上文提到过的)。</p> + +<p>在另一方面,你可以让任一元素看起来像一个顶级标题,如下:</p> + +<pre class="brush: html notranslate"><span style="font-size: 32px; margin: 21px 0;">这是顶级标题吗?</span></pre> + +<p>这是一个 {{htmlelement("span")}} 元素,它没有语义。当您想要对它用CSS(或者JS)时,您可以用它包裹内容,且不需要附加任何额外的意义(在未来的课程中你会发现更多这类元素)。我们已经对它使用了CSS来让它看起来像一个顶级标题。然而,由于它没有语义值,所以它不会有任何上文提到的帮助。最好的方法是使用相关的HTML元素来标记这个项目。</p> + +<h2 id="列表_Lists">列表 Lists</h2> + +<p>现在,让我们学习一下列表。列表在生活中随处可见——从购物清单到回家的路线方案,再到本教程的说明列表。在网络上,列表也随处可见,大致包含了三种不同类型的列表。</p> + +<h3 id="无序_Unordered">无序 Unordered</h3> + +<p>无序列表用于标记列表项目顺序无关紧要的列表 — 让我们以早点清单为例。</p> + +<pre class="notranslate">豆浆 +油条 +豆汁 +焦圈 +</pre> + +<p>每份无序的清单从 {{htmlelement("ul")}} 元素开始——需要包裹清单上所有被列出的项目:</p> + +<pre class="brush: html notranslate"><ul> +豆浆 +油条 +豆汁 +焦圈 +</ul></pre> + +<p>然后就是用 {{htmlelement("li")}} 元素把每个列出的项目单独包裹起来:</p> + +<pre class="brush: html notranslate"><ul> + <li>豆浆</li> + <li>油条</li> + <li>豆汁</li> + <li>焦圈</li> +</ul></pre> + +<h4 id="实践操作_标记无序列表">实践操作: 标记无序列表</h4> + +<p>尝试编辑下面的示例来创建一个HTML无序列表。</p> + +<div class="hidden"> +<h6 id="Playable_code_2">Playable code 2</h6> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html lang="zh-CN"> + <head> + <meta charset="utf-8"> + <style> + body { font-family: '微软雅黑', Helvetica, Arial, sans-serif; margin: 10px; background: #f5f9fa; } + h2 { font-size: 16px; } + code, textarea { font-family: Consolas, Menlo, monospace; } + .output { min-height: 100px; } + .input { min-height: 100px; width: 95%; } + .a11y-label { margin: 0; text-align: right; font-size: 0.7rem; width: 98%; } + .controls { width: 96%; text-align: right; } + </style> + + </head> + <body> + <h2>实时输出</h2> + <div class="output"></div> + + <h2>可编辑代码</h2> + <p class="a11y-label">按 ESC 退出编辑区域,按 Tab 可插入制表符 <code>'\t'</code> </p> + <textarea id="code" class="input"></textarea> + + <div class="controls"> + <button id="btn-reset">重置</button> + <button id="btn-solution">显示答案</button> + </div> + <script> + const btnReset = document.getElementById('btn-reset'); + const btnSolution = document.getElementById('btn-solution'); + const blockOutput = document.querySelector('.output'); + const blockInput = document.querySelector('.input'); + const original = '豆浆 油条 豆汁 焦圈'; + const answer = +`<ul> +<li>豆浆</li> +<li>油条</li> +<li>豆汁</li> +<li>焦圈</li> +</ul>`; + let userEntry = ""; + + init(); + btnReset.addEventListener('click', init); + + btnSolution.addEventListener('click', () => { + if (btnSolution.textContent === '显示答案') { + blockInput.value = + blockOutput.innerHTML = answer; + btnSolution.textContent = '隐藏答案'; + } else { + blockInput.value = + blockOutput.innerHTML = userEntry; + btnSolution.textContent = '显示答案'; + } + }); + + blockInput.addEventListener('keydown', (e) => { + switch (e.key) { + case 'Tab': + e.preventDefault(); + insertAtCursor('\t'); + break; + case "Escape": + blockInput.blur(); + break; + } + }); + + blockInput.addEventListener('keyup', () => { + userEntry = blockInput.value; + blockOutput.innerHTML = blockInput.value; + if (btnSolution.textContent === '隐藏答案') { + btnSolution.textContent = '显示答案'; + } + }); + + function init() { + userEntry = + blockOutput.innerHTML = + blockInput.value = original; + btnSolution.textContent = '显示答案'; + } + + function insertAtCursor(text) { + const scrollPos = blockInput.scrollTop; + const cursorPos = blockInput.selectionStart; + + const front = blockInput.value.substring(0, cursorPos); + const back = blockInput.value.substring( + blockInput.selectionEnd, blockInput.value.length); + + blockInput.value = front + text + back; + blockInput.selectionStart = + blockInput.selectionEnd = cursorPos + text.length; + blockInput.focus(); + blockInput.scrollTop = scrollPos; + } + </script> + </body> +</html> +</pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code_2', 700, 400, "", "", "hide-codepen-jsfiddle") }}</p> + +<h3 id="有序_Ordered">有序 Ordered</h3> + +<p>有序列表需要按照项目的顺序列出来——让我们以一组方向为例:</p> + +<pre class="notranslate">沿着条路走到头 +右转 +直行穿过第一个十字路口 +在第三个十字路口处左转 +继续走 300 米,学校就在你的右手边 +</pre> + +<p>这个标记的结构和无序列表一样,除了需要用{{htmlelement("ol")}} 元素将所有项目包裹, 而不是<code><ul>:</code></p> + +<pre class="brush: html notranslate"><ol> + <li>沿着条路走到头</li> + <li>右转</li> + <li>直行穿过第一个十字路口</li> + <li>在第三个十字路口处左转</li> + <li>继续走 300 米,学校就在你的右手边</li> +</ol></pre> + +<h4 id="实践操作_标记有序列表">实践操作: 标记有序列表</h4> + +<p>尝试编辑下面的示例来创建一个HTML有序列表:</p> + +<div class="hidden"> +<h6 id="Playable_code_3">Playable code 3</h6> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html lang="zh-CN"> + <head> + <meta charset="utf-8"> + <style> + body { font-family: '微软雅黑', Helvetica, Arial, sans-serif; margin: 10px; background: #f5f9fa; } + h2 { font-size: 16px; } + code, textarea { font-family: Consolas, Menlo, monospace; } + .output { min-height: 120px; } + .input { min-height: 120px; width: 95%; } + .a11y-label { margin: 0; text-align: right; font-size: 0.7rem; width: 98%; } + .controls { width: 96%; text-align: right; } + </style> + + </head> + <body> + <h2>实时输出</h2> + <div class="output"></div> + + <h2>可编辑代码</h2> + <p class="a11y-label">按 ESC 退出编辑区域,按 Tab 可插入制表符 <code>'\t'</code> </p> + <textarea id="code" class="input"></textarea> + + <div class="controls"> + <button id="btn-reset">重置</button> + <button id="btn-solution">显示答案</button> + </div> + <script> + const btnReset = document.getElementById('btn-reset'); + const btnSolution = document.getElementById('btn-solution'); + const blockOutput = document.querySelector('.output'); + const blockInput = document.querySelector('.input'); + const original = +`沿着条路走到头 +右转 +直行穿过第一个十字路口 +在第三个十字路口处左转 +继续走 300 米,学校就在你的右手边`; + const answer = +`<ol> + <li>沿着条路走到头</li> + <li>右转</li> + <li>直行穿过第一个十字路口</li> + <li>在第三个十字路口处左转</li> + <li>继续走 300 米,学校就在你的右手边</li> +</ol>`; + let userEntry = ""; + + init(); + btnReset.addEventListener('click', init); + + btnSolution.addEventListener('click', () => { + if (btnSolution.textContent === '显示答案') { + blockInput.value = + blockOutput.innerHTML = answer; + btnSolution.textContent = '隐藏答案'; + } else { + blockInput.value = + blockOutput.innerHTML = userEntry; + btnSolution.textContent = '显示答案'; + } + }); + + blockInput.addEventListener('keydown', (e) => { + switch (e.key) { + case 'Tab': + e.preventDefault(); + insertAtCursor('\t'); + break; + case "Escape": + blockInput.blur(); + break; + } + }); + + blockInput.addEventListener('keyup', () => { + userEntry = blockInput.value; + blockOutput.innerHTML = blockInput.value; + if (btnSolution.textContent === '隐藏答案') { + btnSolution.textContent = '显示答案'; + } + }); + + function init() { + userEntry = + blockOutput.innerHTML = + blockInput.value = original; + btnSolution.textContent = '显示答案'; + } + + function insertAtCursor(text) { + const scrollPos = blockInput.scrollTop; + const cursorPos = blockInput.selectionStart; + const front = blockInput.value.substring(0, cursorPos); + const back = blockInput.value.substring( + blockInput.selectionEnd, blockInput.value.length); + blockInput.value = front + text + back; + blockInput.selectionStart = + blockInput.selectionEnd = cursorPos + text.length; + blockInput.focus(); + blockInput.scrollTop = scrollPos; + } + </script> + </body> +</html></pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code_3', 700, 500, "", "", "hide-codepen-jsfiddle") }}</p> + +<h3 id="实践操作_标记我们的食谱">实践操作: 标记我们的食谱</h3> + +<p>到了这里,你拥有了所有你需要的信息来标记我们的食谱样例。你可以选择从<a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/html-text-formatting/text-start.html">text-start.html</a>复制一份文件并保存在本地,打开它进行编辑,或者在下面的例子中进行编辑。因为在本地你可以保存你的项目,所以在本地做这个工作可能更好。而如果你在下面可编辑的样本中作业,下一次你打开这个网站时你可能会丢失你的数据。各有利弊吧。</p> + +<div class="hidden"> +<h6 id="Playable_code_4">Playable code 4</h6> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html lang="zh-CN"> + <head> + <meta charset="utf-8"> + <style> + body { font-family: '微软雅黑', Helvetica, Arial, sans-serif; margin: 10px; background: #f5f9fa; } + h2 { font-size: 16px; } + code, textarea { font-family: Consolas, Menlo, monospace; } + .output { min-height: 200px; } + .input { min-height: 200px; width: 95%; } + .a11y-label { margin: 0; text-align: right; font-size: 0.7rem; width: 98%; } + .controls { width: 96%; text-align: right; } + </style> + + </head> + <body> + <h2>实时输出</h2> + <div class="output"></div> + + <h2>可编辑代码</h2> + <p class="a11y-label">按 ESC 退出编辑区域,按 Tab 可插入制表符 <code>'\t'</code> </p> + <textarea id="code" class="input"></textarea> + + <div class="controls"> + <button id="btn-reset">重置</button> + <button id="btn-solution">显示答案</button> + </div> + <script> + const btnReset = document.getElementById('btn-reset'); + const btnSolution = document.getElementById('btn-solution'); + const blockOutput = document.querySelector('.output'); + const blockInput = document.querySelector('.input'); + const original = +`宫保鸡丁的做法 +宫保鸡丁,川菜系中的传统名菜,由鸡丁、干辣椒、花生米等炒制而成。由于其入口鲜辣,鸡肉的鲜嫩配合花生的香脆,广受大众欢迎。 +相传宫保鸡丁是清朝光绪年间的署理四川总督丁宝桢所发明,是他招待客人时叫家厨煮的菜肴。由于丁宝桢后来被封为东宫少保(太子少保),所以被称为“丁宫保”,而这道菜亦被称为“宫保鸡丁” + +原料 +去骨鸡胸肉:一斤八两 +干红辣椒:八钱 +炸花生米:一两五钱 +花椒粒:两大匙 +葱:两根(切段) +蛋白:一个 +淀粉:三大匙 +酱油:两大匙 +蒜末:半茶匙 +糖:半茶匙 +白醋:一茶匙 +色拉油:适量 +盐:两茶匙 + +做法 +先用蛋白一个、盐半茶匙及淀粉两大匙搅拌均匀,调成“腌料”,鸡胸肉切成约一厘米见方的碎丁并用“腌料”搅拌均匀,腌渍半小时。 +用酱油一大匙、淀粉水一大匙、糖半茶匙、盐四分之一茶匙、白醋一茶匙、蒜末半茶匙调拌均匀,调成“综合调味料”。 +鸡丁腌好以后,色拉油下锅烧热,先将鸡丁倒入锅内,用大火快炸半分钟,炸到变色之后,捞出来沥干油汁备用。 +在锅里留下约两大匙油,烧热后将切好的干辣椒下锅,用小火炒香后,再放入花椒粒和葱段一起爆香。随后鸡丁重新下锅,用大火快炒片刻后,再倒入“综合调味料”继续快炒。 +如果你采用正宗川菜做法,最后只需加入花生米,炒拌几下就可以起锅了。 +如果你在北方,可加入黄瓜丁、胡萝卜丁和花生米,翻炒后起锅。 + +大千鸡 +张大千居加拿大期间,曾按自己喜好改变宫保鸡丁的做法,并传授当地厨师,厨师将之命名为“大千鸡”,以兹纪念。大千鸡与宫保鸡丁不同之处,是使用经细工去皮、出骨、剔膜的鸡腿肉,以干辣椒、豆瓣酱为味,而且不用花生。 +`; + const answer = +`<h1>宫保鸡丁的做法</h1> +<p>宫保鸡丁,川菜系中的传统名菜,由鸡丁、干辣椒、花生米等炒制而成。由于其入口鲜辣,鸡肉的鲜嫩配合花生的香脆,广受大众欢迎。</p> +<p>相传宫保鸡丁是清朝光绪年间的署理四川总督丁宝桢所发明,是他招待客人时叫家厨煮的菜肴。由于丁宝桢后来被封为东宫少保(太子少保),所以被称为“丁宫保”,而这道菜亦被称为“宫保鸡丁”</p> + +<h2>原料</h2> +<ul> + <li>去骨鸡胸肉:一斤八两</li> + <li>干红辣椒:八钱</li> + <li>炸花生米:一两五钱</li> + <li>花椒粒:两大匙</li> + <li>葱:两根(切段)</li> + <li>蛋白:一个</li> + <li>淀粉:三大匙</li> + <li>酱油:两大匙</li> + <li>蒜末:半茶匙</li> + <li>糖:半茶匙</li> + <li>白醋:一茶匙</li> + <li>色拉油:适量</li> + <li>盐:两茶匙</li> +</ul> + +<h2>做法</h2> +<ol> + <li>先用蛋白一个、盐半茶匙及淀粉两大匙搅拌均匀,调成“腌料”,鸡胸肉切成约一厘米见方的碎丁并用“腌料”搅拌均匀,腌渍半小时。</li> + <li>用酱油一大匙、淀粉水一大匙、糖半茶匙、盐四分之一茶匙、白醋一茶匙、蒜末半茶匙调拌均匀,调成“综合调味料”。</li> + <li>鸡丁腌好以后,色拉油下锅烧热,先将鸡丁倒入锅内,用大火快炸半分钟,炸到变色之后,捞出来沥干油汁备用。</li> + <li>在锅里留下约两大匙油,烧热后将切好的干辣椒下锅,用小火炒香后,再放入花椒粒和葱段一起爆香。随后鸡丁重新下锅,用大火快炒片刻后,再倒入“综合调味料”继续快炒。</li> + <li>如果你采用正宗川菜做法,最后只需加入花生米,炒拌几下就可以起锅了。</li> + <li>如果你在北方,可加入黄瓜丁、胡萝卜丁和花生米,翻炒后起锅。</li> +</ol> + +<h2>大千鸡</h2> +<p>张大千居加拿大期间,曾按自己喜好改变宫保鸡丁的做法,并传授当地厨师,厨师将之命名为“大千鸡”,以兹纪念。大千鸡与宫保鸡丁不同之处,是使用经细工去皮、出骨、剔膜的鸡腿肉,以干辣椒、豆瓣酱为味,而且不用花生。</p>`; + let userEntry = ""; + + init(); + btnReset.addEventListener('click', init); + + btnSolution.addEventListener('click', () => { + if (btnSolution.textContent === '显示答案') { + blockInput.value = + blockOutput.innerHTML = answer; + btnSolution.textContent = '隐藏答案'; + } else { + blockInput.value = + blockOutput.innerHTML = userEntry; + btnSolution.textContent = '显示答案'; + } + }); + + blockInput.addEventListener('keydown', (e) => { + switch (e.key) { + case 'Tab': + e.preventDefault(); + insertAtCursor('\t'); + break; + case "Escape": + blockInput.blur(); + break; + } + }); + + blockInput.addEventListener('keyup', () => { + userEntry = blockInput.value; + blockOutput.innerHTML = blockInput.value; + if (btnSolution.textContent === '隐藏答案') { + btnSolution.textContent = '显示答案'; + } + }); + + function init() { + userEntry = + blockOutput.innerHTML = + blockInput.value = original; + btnSolution.textContent = '显示答案'; + } + + function insertAtCursor(text) { + const scrollPos = blockInput.scrollTop; + const cursorPos = blockInput.selectionStart; + + const front = blockInput.value.substring(0, cursorPos); + const back = blockInput.value.substring( + blockInput.selectionEnd, blockInput.value.length); + + blockInput.value = front + text + back; + blockInput.selectionStart = + blockInput.selectionEnd = cursorPos + text.length; + blockInput.focus(); + blockInput.scrollTop = scrollPos; + } + </script> + </body> +</html></pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code_4', 700, 800, "", "", "hide-codepen-jsfiddle") }}</p> + +<p>如果你感到棘手,你可以随时按下<em>Show solution</em>按钮,或者在我们的github repo上检查我们的 <a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/html-text-formatting/text-complete.html">text-complete.html</a> 样例。</p> + +<h3 id="嵌套列表_Nesting_lists">嵌套列表 Nesting lists</h3> + +<p><span id="result_box" lang="zh-CN"><span>将一个列表嵌入到另一个列表是完全可以的。</span> <span>你可能想让一些子项目列在首项目之下。</span><span>让我们从食谱示例中获取第二个列表:</span></span></p> + +<pre class="brush: html notranslate"><ol> + <li>先用蛋白一个、盐半茶匙及淀粉两大匙搅拌均匀,调成“腌料”,鸡胸肉切成约一厘米见方的碎丁并用“腌料”搅拌均匀,腌渍半小时。</li> + <li>用酱油一大匙、淀粉水一大匙、糖半茶匙、盐四分之一茶匙、白醋一茶匙、蒜末半茶匙调拌均匀,调成“综合调味料”。</li> + <li>鸡丁腌好以后,色拉油下锅烧热,先将鸡丁倒入锅内,用大火快炸半分钟,炸到变色之后,捞出来沥干油汁备用。</li> + <li>在锅里留下约两大匙油,烧热后将切好的干辣椒下锅,用小火炒香后,再放入花椒粒和葱段一起爆香。随后鸡丁重新下锅,用大火快炒片刻后,再倒入“综合调味料”继续快炒。</li> + <li>如果你采用正宗川菜做法,最后只需加入花生米,炒拌几下就可以起锅了。</li> + <li>如果你在北方,可加入黄瓜丁、胡萝卜丁和花生米,翻炒后起锅。</li> + </ol></pre> + +<p>由于最后两项与它们的前一项非常密切相关(它们看起来更像该项的子项或选项),将它们编辑成无序列表,并嵌套在该项的子项中可能更合理。就像下面这样:</p> + +<pre class="brush: html notranslate"><ol> + <li>先用蛋白一个、盐半茶匙及淀粉两大匙搅拌均匀,调成“腌料”,鸡胸肉切成约一厘米见方的碎丁并用“腌料”搅拌均匀,腌渍半小时。</li> + <li>用酱油一大匙、淀粉水一大匙、糖半茶匙、盐四分之一茶匙、白醋一茶匙、蒜末半茶匙调拌均匀,调成“综合调味料”。</li> + <li>鸡丁腌好以后,色拉油下锅烧热,先将鸡丁倒入锅内,用大火快炸半分钟,炸到变色之后,捞出来沥干油汁备用。</li> + <li>在锅里留下约两大匙油,烧热后将切好的干辣椒下锅,用小火炒香后,再放入花椒粒和葱段一起爆香。随后鸡丁重新下锅,用大火快炒片刻后,再倒入“综合调味料”继续快炒。 + <ul> + <li>如果你采用正宗川菜做法,最后只需加入花生米,炒拌几下就可以起锅了。</li> + <li>如果你在北方,可加入黄瓜丁、胡萝卜丁和花生米,翻炒后起锅。</li> + </ul> + </li> +</ol></pre> + +<p>尝试回到上一个实践操作的例子中,并更新第二个列表。</p> + +<h2 id="重点强调">重点强调</h2> + +<p>在日常用语中,我们常常会加重某个字的读音,或者用加粗等方式突出某句话的重点。与此类似,HTML 也提供了相应的标签,用于标记某些文本,使其具有加粗、倾斜、下划线等效果。下面,我们将学习一些最常见的标签。</p> + +<h3 id="强调">强调</h3> + +<p>在口语表达中,我们有时会强调某些字,用来改变这句话的意思。同样地,在书面用语中,我们可以使用斜体字来达到同样的效果。例如,下面两个句子便有不同的意思:</p> + +<p>I am glad you weren't late.</p> + +<p>I am <em>glad</em> you weren't <em>late</em>. (ps: 此句中"<em>glad"</em>和"late"为斜体字体)</p> + +<p>第一句话听起来真的像松了一口气因为没有迟到。相反,第二句话听起来具有讽刺性而且有隐含的攻击性,表达对一个人迟到的恼怒。</p> + +<p>在HTML中我们用{{htmlelement("em")}}(emphasis)元素来标记这样的情况。这样做既可以让文档读起来更有趣,也可以被屏幕阅读器识别出来,并以不同的语调发出。浏览器默认风格为斜体,但你不应该纯粹使用这个标签来获得斜体风格,为了获得斜体风格,你应该使用{{htmlelement("span")}}元素和一些CSS,或者是{{htmlelement("i")}}元素(见下文)。</p> + +<pre class="brush: html notranslate"><p>I am <em>glad</em> you weren't <em>late</em>.</p></pre> + +<h3 id="非常重要">非常重要</h3> + +<p>为了强调重要的词,在口语方面我们往往用重音强调,在文字方面则是用粗体字来达到强调的效果。例如下面这段:</p> + +<p>This liquid is <strong>highly toxic</strong>.</p> + +<p>I am counting on you. <strong>Do not</strong> be late!</p> + +<p>在HTML中我们用{{htmlelement("strong")}} (strong importance) 元素来标记这样的请况。这样做既可以让文档更加地有用,也可以被屏幕阅读器识别出来,并以不同的语调发出。浏览器默认风格为粗体,但你不应该纯粹使用这个标签来获得粗体风格,为了获得粗体风格,你应该使用{{htmlelement("span")}}元素和一些CSS,或者是 {{htmlelement("b")}} 元素 (见下文)。</p> + +<pre class="brush: html notranslate"><p>This liquid is <strong>highly toxic</strong>.</p> + +<p>I am counting on you. <strong>Do not</strong> be late!</p></pre> + +<p>如有需要你可以将strong元素和em元素嵌套在其他的标签中:</p> + +<pre class="brush: html notranslate"><p>This liquid is <strong>highly toxic</strong> — +if you drink it, <strong>you may <em>die</em></strong>.</p></pre> + +<h3 id="实践操作_我们是重要的!">实践操作: 我们是重要的!</h3> + +<p>在这个实践操作中,我们提供了可编辑的例子。在这个例子中,我们想让你把斜体(em)和加粗(strong)放在你认为重要的词汇上,仅仅为了练习。</p> + +<div class="hidden"> +<h6 id="Playable_code_5">Playable code 5</h6> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html lang="zh-CN"> + <head> + <meta charset="utf-8"> + <style> + body { font-family: '微软雅黑', Helvetica, Arial, sans-serif; margin: 10px; background: #f5f9fa; } + h2 { font-size: 16px; } + code, textarea { font-family: Consolas, Menlo, monospace; } + .output { min-height: 150px; } + .input { min-height: 150px; width: 95%; } + .a11y-label { margin: 0; text-align: right; font-size: 0.7rem; width: 98%; } + .controls { width: 96%; text-align: right; } + </style> + + </head> + <body> + <h2>实时输出</h2> + <div class="output"></div> + + <h2>可编辑代码</h2> + <p class="a11y-label">按 ESC 退出编辑区域,按 Tab 可插入制表符 <code>'\t'</code> </p> + <textarea id="code" class="input"></textarea> + + <div class="controls"> + <button id="btn-reset">重置</button> + <button id="btn-solution">显示答案</button> + </div> + <script> + const btnReset = document.getElementById('btn-reset'); + const btnSolution = document.getElementById('btn-solution'); + const blockOutput = document.querySelector('.output'); + const blockInput = document.querySelector('.input'); + const original = +`AlphaGo 李世乭五番棋 + +<p>2016年3月8日到3月15日,韩国职业棋士李世乭(이세돌)九段与由 Google DeepMind 开发的计算机围棋软件 AlphaGo 对弈的五局三胜制围棋比赛在韩国首尔举行。结果为 AlphaGo 以四胜一负的战绩击败李世乭。赛后韩国棋院授予 AlphaGo 荣誉九段的称号。</p>`; + const answer = +`<h1>AlphaGo 李世乭五番棋</h1> + +<p><strong>2016年3月8日</strong>到<strong>3月15日</strong>,韩国职业棋士<strong>李世乭(이세돌)<em>九段</em></strong>与由 Google DeepMind 开发的计算机围棋软件 <strong>AlphaGo</strong> 对弈的五局三胜制围棋比赛在韩国<strong>首尔</strong>举行。结果为 AlphaGo 以<strong>四胜一负</strong>的战绩击败李世乭。赛后韩国棋院授予 AlphaGo <strong>荣誉九段</strong>的称号。</p>`; + let userEntry = ""; + + init(); + btnReset.addEventListener('click', init); + + btnSolution.addEventListener('click', () => { + if (btnSolution.textContent === '显示答案') { + blockInput.value = + blockOutput.innerHTML = answer; + btnSolution.textContent = '隐藏答案'; + } else { + blockInput.value = + blockOutput.innerHTML = userEntry; + btnSolution.textContent = '显示答案'; + } + }); + + blockInput.addEventListener('keydown', (e) => { + switch (e.key) { + case 'Tab': + e.preventDefault(); + insertAtCursor('\t'); + break; + case "Escape": + blockInput.blur(); + break; + } + }); + + blockInput.addEventListener('keyup', () => { + userEntry = blockInput.value; + blockOutput.innerHTML = blockInput.value; + if (btnSolution.textContent === '隐藏答案') { + btnSolution.textContent = '显示答案'; + } + }); + + function init() { + userEntry = + blockOutput.innerHTML = + blockInput.value = original; + btnSolution.textContent = '显示答案'; + } + + function insertAtCursor(text) { + const scrollPos = blockInput.scrollTop; + const cursorPos = blockInput.selectionStart; + + const front = blockInput.value.substring(0, cursorPos); + const back = blockInput.value.substring( + blockInput.selectionEnd, blockInput.value.length); + + blockInput.value = front + text + back; + blockInput.selectionStart = + blockInput.selectionEnd = cursorPos + text.length; + blockInput.focus(); + blockInput.scrollTop = scrollPos; + } + </script> + </body> +</html></pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code_5', 700, 500, "", "", "hide-codepen-jsfiddle") }}</p> + +<h3 id="斜体字、粗体字、下划线...">斜体字、粗体字、下划线...</h3> + +<p>迄今为止我们已经讨论的元素都是意义清楚的语义元素。{{htmlelement("b")}}, {{htmlelement("i")}}, 和 {{htmlelement("u")}} 的情况却有点复杂。它们出现于人们要在文本中使用粗体、斜体、下划线但CSS仍然不被完全支持的时期。像这样的元素,仅仅影响表象而且没有语义,被称为<strong>表象元素(presentational elements)</strong>并且不应该再被使用。因为正如我们在之前看到的,语义对可访问性,SEO(搜索引擎优化)等非常重要。</p> + +<p>HTML5用新的语义规则重新定义了<code><b></code>,<code><i></code>和<code><u></code>,使得它们的语言显得稍微有点混乱。</p> + +<p>这里是最好的经验法则:如果没有更合适的元素,那么使用 <code><b></code>、<code><i></code> 或 <code><u></code> 来表达传统上的粗体、斜体或下划线表达的意思是合适的。然而,始终拥有<a href="/zh-CN/docs/learn/Accessibility">可访问性</a>的思维模式是至关重要的。斜体的概念对人们使用屏幕阅读器是没有帮助的,对使用其他书写系统而不是拉丁文书写系统的人们也是没有帮助的。</p> + +<ul> + <li>{{HTMLElement('i')}} 被用来传达传统上用斜体表达的意义:外国文字,分类名称,技术术语,一种思想……</li> + <li>{{HTMLElement('b')}} 被用来传达传统上用粗体表达的意义:关键字,产品名称,引导句……</li> + <li>{{HTMLElement('u')}} 被用来传达传统上用下划线表达的意义:专有名词,拼写错误……</li> +</ul> + +<div class="note"> +<p>使用下划线的忠告:因为我们常常会认为网页中的下划线代表着一个超链接<strong>,</strong>所以最好只用下划线来代表超链接。而在语义适合的情况下不得不使用<u>元素时,可以使用CSS来改变<u>元素对应的下划线的默认样式,从而和超链接的下划线区分开来。下面是一个具体的例子:</p> +</div> + +<pre class="brush: html notranslate"><!-- 学名 --> +<p> + 红喉北蜂鸟(学名:<i>Archilocus colubris</i>) + 是北美东部最常见的蜂鸟品种。 +</p> + +<!-- 舶来词 --> +<p> + 菜单上有好多舶来词汇,比如 <i lang="uk-latn">vatrushka</i>(东欧乳酪面包), + <i lang="id">nasi goreng</i>(印尼炒饭)以及<i lang="fr">soupe à l'oignon</i>(法式洋葱汤)。 +</p> + +<!-- 已知的错误书写 --> +<p> + 总有一天我会改掉写<u style="text-decoration-line: underline; text-decoration-style: wavy;">措字</u>的毛病。 +</p> + +<!-- 在一组指令中突出显示关键字 --> +<ol> + <li> + <b>切</b>下两片面包, + </li> + <li> + 在两片面包中间<b>夹入</b>一片西红柿和一片生菜叶。 + </li> +</ol></pre> + +<h2 id="总结">总结</h2> + +<p>至此,本文应该给您做了一个很好的了解,如何开始在HTML中标记文本,并介绍了一些最重要的元素。在这一领域还有许多语义元素,<span id="result_box" lang="zh-CN"><span>我们将在后面的“更多语义元素”文章中看到更多的语义元素。</span> <span>在下一篇文章中,我们将详细介绍如何创建超链接(</span></span><a href="/en-US/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks">create hyperlinks</a><span lang="zh-CN"><span>),它可能是Web上最重要的元素。</span></span></p> + +<p>{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML", "Learn/HTML/Introduction_to_HTML/Creating_hyperlinks", "Learn/HTML/Introduction_to_HTML")}}</p> + +<h2 id="本章目录">本章目录</h2> + +<ul> + <li><a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/Getting_started">开始学习 HTML</a></li> + <li><a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML">“头”里有什么?HTML 元信息</a></li> + <li><a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/HTML_text_fundamentals">HTML 文字处理初步</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks">创建超链接</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Advanced_text_formatting">高级文字格式</a></li> + <li><a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/文件和网站结构">文档和站点结构</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Debugging_HTML">HTML 调试</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Marking_up_a_letter">课程测验:为信件排版</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Structuring_a_page_of_content">课程测验:构建内容丰富的网页</a></li> +</ul> diff --git a/files/zh-cn/learn/html/introduction_to_html/index.html b/files/zh-cn/learn/html/introduction_to_html/index.html new file mode 100644 index 0000000000..4452927531 --- /dev/null +++ b/files/zh-cn/learn/html/introduction_to_html/index.html @@ -0,0 +1,67 @@ +--- +title: HTML 介绍 +slug: learn/HTML/Introduction_to_HTML +tags: + - HTML介绍 + - 文本 + - 结构 + - 链接 +translation_of: Learn/HTML/Introduction_to_HTML +--- +<div>{{LearnSidebar}}</div> + +<p class="summary">就其核心而言, {{glossary("HTML")}} 是一种相当简单的、由不同<a href="https://developer.mozilla.org/zh-CN/docs/Glossary/元素" title="zh-CN/docs/Glossary/Element">元素</a>组成的标记语言,它可以应用于文本片段,使文本在文档中具有不同的含义(它是一个段落吗?它是一个项目列表吗?它是一个表格吗?),将文档结构化为逻辑块(文档是否有头部?有三列内容?有一个导航菜单?),并且可以将图片,影像等内容嵌入到页面中。本模块将介绍前两个,并且介绍一些理解HTML所需的基本概念和语法。</p> + +<h2 id="前提">前提</h2> + +<p>在开始这个模块之前,你不需要预先具有任何HTML的知识,但是你需要至少熟悉一些使用电脑的基础,会被动地使用网络(也就是仅需要看着它,浏览内容)。你应该为电脑配置一个基本的工作环境,这在<a href="https://developer.mozilla.org/zh-CN/docs/Learn/Getting_started_with_the_web/Installing_basic_software">安装基本软件</a>的页面中有详细说明,并且需要懂得如何创建和管理文件,这在<a href="https://developer.mozilla.org/zh-CN/docs/Learn/Getting_started_with_the_web/Dealing_with_files">处理文件</a>页面中有详细说明 —— 它们都是我们纯新手<a href="https://developer.mozilla.org/zh-CN/docs/Learn/Getting_started_with_the_web">web开发入门</a>模块的一部分。</p> + +<div class="note"> +<p><strong>注意:</strong>如果你工作在一个无权创建自己文件的电脑/平板/其他设备上,你需要在一个在线编程工具上试验 (大多数)代码示例,如 <a href="http://jsbin.com/">JSBin</a> 或者 <a href="https://glitch.com/">Glitch</a>等。</p> +</div> + +<h2 id="指南">指南</h2> + +<p>这个模块包含以下文章,这些文章会帮你过一遍HTML所有的基本理论,并且提供足够的实践机会。</p> + +<dl> + <dt><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Getting_started">HTML入门</a></dt> + <dd>涵盖了HTML绝对基础的知识来帮助你入门——我们定义元素、属性和其他重要术语,以及它们属于语言的哪个部分。我们也会展示一个典型的HTML 页面是如何被结构化的,以及一个 HTML 元素是如何被结构化的 ,并且解释另一些基础但重要的语言特性。一路下来,我们会与一些 HTML一起玩耍,来激发你的兴趣!</dd> + <dt><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML">Head中有什么?HTML中的元数据</a></dt> + <dd>当页面被加载后HTML中的head部分<strong>是不会</strong>被显示在web浏览器中的。它包含了许多信息,例如网页的标题{{htmlelement("title")}},指向{{glossary("CSS")}}的链接(如果你想用CSS来设计HTML内容的样式),指向自定义网站图标的链接和一些元数据(关于HTML本身的数据,例如它的作者和描述这个文档的关键字)。</dd> + <dt><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals">HTML 文字处理基础 </a></dt> + <dd>HTML的主要工作之一就是给予文本意义(也被叫做<strong>语义</strong>),所以浏览器就知道如何正确的显示文本了。这篇文章关注于如何用HTML来将文本块分解为结构化的标题和段落、强调和加粗单词 、创建列表和其他。</dd> + <dt><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks">创建超链接</a></dt> + <dd>超链接真的很重要 - 它们是使Web成为一个Web。本文介绍了创建链接所需的语法,并讨论了链接的最佳实践。</dd> + <dt><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Advanced_text_formatting">高级文本排版</a></dt> + <dd>HTML中有许多其他元素可以用于格式化文本,我们没有在<a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals">HTML 文字处理基础</a>中提到它们。这些元素不太知名,但了解它们仍然有用。在这篇文章里,你将学习如何标记引文、描述列表、计算机代码和其他类似的文本、下标和上标、联系信息等。</dd> + <dt><a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/文件和网站结构">文档和网站结构</a></dt> + <dd>除了定义页面的各个部分(例如“段落”或“图像”)外,HTML也用于定义网站的区域(例如“标题”,“导航菜单”,“主内容列“)。本文探讨如何规划基本网站结构,以及如何编写HTML以表示此结构。</dd> + <dt><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Debugging_HTML">调试 HTML</a></dt> + <dd>编写HTML是好的,但如果出现了什么问题,而且你没能找到代码中的错误在哪里的话,本文将向你介绍一些可以帮上忙的工具。</dd> +</dl> + +<h2 id="考核">考核</h2> + +<p>以下考核将测试你对上述指南中HTML基础知识的理解。</p> + +<dl> + <dt><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Marking_up_a_letter">制造一份信件</a></dt> + <dd>我们或早或晚都学会了如何写一封信,这也是一个不错的用来测试我们的文本格式化技能例子!所以在这个评估中,你会得到一封信来标记。</dd> + <dt><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Structuring_a_page_of_content"> 结构化页面内容</a></dt> + <dd>此评估测试你能否使用HTML构建简单的内容页面,其中包含页眉、页脚、导航菜单、主要内容和侧边栏。</dd> +</dl> + +<h2 id="相关链接">相关链接</h2> + +<dl> + <dt><a href="https://teach.mozilla.org/activities/web-lit-basics/">网络文化基础 1</a></dt> + <dd>一个优秀的Mozilla基础课程,探索和测试在HTML模块介绍中讨论的许多技能。学习者熟悉阅读,写作和参与这个六部分模块的网络。通过生产和协作掌握网络的基础。</dd> + <dt></dt> +</dl> + +<div class="note"> +<h2 id="反馈">反馈</h2> + +<p><a href="https://www.surveygizmo.com/s3/4871248/MDN-Guides-Survey">点击这里进入我们的调查</a>来协助我们完善这份指南和教程.</p> +</div> diff --git a/files/zh-cn/learn/html/introduction_to_html/marking_up_a_letter/index.html b/files/zh-cn/learn/html/introduction_to_html/marking_up_a_letter/index.html new file mode 100644 index 0000000000..fc20a9c177 --- /dev/null +++ b/files/zh-cn/learn/html/introduction_to_html/marking_up_a_letter/index.html @@ -0,0 +1,103 @@ +--- +title: 标记信件 +slug: learn/HTML/Introduction_to_HTML/Marking_up_a_letter +tags: + - HTML + - 初学者 + - 文件头 + - 文本 + - 标记 + - 格式 + - 测验 + - 超链接 +translation_of: Learn/HTML/Introduction_to_HTML/Marking_up_a_letter +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/Debugging_HTML", "Learn/HTML/Introduction_to_HTML/Structuring_a_page_of_content", "Learn/HTML/Introduction_to_HTML")}}</div> + +<p class="summary">写信是每个人的必备技能,它也是测验文本格式化技能的一个不错的办法呀! 本次测验要求你为你一封写好的信做出标记,以测验你基础和高级的 HTML 文本格式化技能,包括超链接等等。此外将测验你对一些 HTML <code><head></code> 内容的熟悉程度。</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">预备知识:</th> + <td>阅读并掌握以下文章的内容:<a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/Getting_started">开始学习 HTML</a> 、<a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML">“头”里有什么?HTML 元信息</a>、<a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/HTML_text_fundamentals">HTML 文字处理初步</a>、<a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks">创建超链接</a> 和 <a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Advanced_text_formatting">高级文字格式</a>。</td> + </tr> + <tr> + <th scope="row">学习目标:</th> + <td>测验对 HTML 文本格式和超链接基本和高级用法、HTML <code><head></code> 内容的理解程度。</td> + </tr> + </tbody> +</table> + +<h2 id="起点">起点</h2> + +<p>开始测验之前,请先<a href="https://github.com/roy-tian/learning-area/tree/master/html/introduction-to-html/marking-up-a-letter-start">下载信件的起始文本和CSS代码</a>。然后用文本编辑器(用 <a class="external-icon external" href="http://jsbin.com/">JSBin</a> 或 <a class="external-icon external" href="https://thimble.mozilla.org/">himble</a> 等在线编辑工具亦可)创建一个新的 <code>.html</code> 文件来进行测验。</p> + +<h2 id="项目概要">项目概要</h2> + +<p>本项目中,你的任务为一封大学内网信件进行标记,这封信是研究人员对一名学生有关申请博士学位问题的回复。</p> + +<p>块/结构语义:</p> + +<ul> + <li>你应该使用适当的结构来构造整体文档,包括doctype、<a href="https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/html" title="HTML <html>元素表示HTML文档的根(顶层元素),因此也称为根元素。所有其他元素必须是此元素的后代。"><code><html></code></a> 、 <a href="https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/head" title="HTML <head>元素提供有关文档的一般信息(元数据),包括其标题和其脚本和样式表的链接。"><code><head></code></a>和<a href="https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/body" title="HTML <body>元素表示HTML文档的内容。文档中只能有一个<body>元素。"><code><body></code></a>元素。</li> + <li>除下面提到的几点之外,这封信应该被标记成有着段落和标题的结构。 这封信有 1 个顶级标题(“回复:”那行)和 3 个二级标题。</li> + <li>使用适当类型的列表标记该学期的开学时间、学习科目和异域舞蹈。</li> + <li>两个地址应该放在<code><a href="/zh-CN/docs/Web/HTML/Element/address"><address></a></code>元素下. 每行的地址应该放在新的一行而不是新的段落.</li> +</ul> + +<p>内联语义:</p> + +<ul> + <li>应着重显示发信人和收信人的姓名(以及“电话”和“电子邮件”字样)。</li> + <li>用适当的元素把文档中的四个日期标记成机器可读的日期。</li> + <li>为信中第一个地址和第一个日期设置一个类属性“<code>sender-column</code>”,这样就能通过添加CSS 来使它们右对齐,以符合经典信件的布局。</li> + <li>信件正文中有 2 个首字母缩略词/缩写词,标记出它们的扩展形式。</li> + <li>正确标注 6 个下标/上标(位于化学方程式、科学计数法中)。</li> + <li>试着标记至少对两个单词进行着重(<code><strong></code>)/ 强调(<code><em></code>)显示。</li> + <li>有两个地方应加上超链接,要为它们添加适当的标题。链接指向 https://example.com/ 即可。</li> + <li>用适当的元素标记校训和引文。</li> +</ul> + +<p>文档的头部:</p> + +<ul> + <li>用适当的元标签把文档的字符集声明为 utf-8。</li> + <li>用适当的元标签说明信件的作者。</li> + <li>用适当的标签引入我们提供的 CSS 代码。</li> +</ul> + +<h2 id="提示和技巧">提示和技巧</h2> + +<ul> + <li>使用 <a class="external external-icon" href="https://validator.w3.org/">W3C HTML验证器</a> 来验证 HTML,验证通过有额外加分。</li> + <li>完成这个测验不需要任何 CSS 知识,只需把现成的 CSS 放到 HTML 元素里就好。</li> +</ul> + +<h2 id="范例">范例</h2> + +<p>以下截图展示了这封信标记完成后可能的外观(可 <a class="external external-icon" href="https://roy-tian.github.io/learning-area/html/introduction-to-html/marking-up-a-letter-finished/">在线查看</a>)。</p> + +<p><img alt="排版信件截图" src="https://mdn.mozillademos.org/files/16534/letter.jpg" style="border: 1px solid black; display: block; margin: 0px auto;"></p> + +<h2 id="测验">测验</h2> + +<p>如果你是在课堂上进行这个测验,你可以把作品交给导师或教授去打分了。如果你是在自学,也可以在 <a href="https://discourse.mozilla-community.org/t/learning-web-development-marking-guides-and-questions/16294">本节测验的讨论页</a> 或者 <a href="https://wiki.mozilla.org/IRC">Mozilla 聊天室 </a>的 <a href="irc://irc.mozilla.org/mdn">#mdn</a> 频道取得帮助。要自己先尝试,作弊是不会有收获的!</p> + +<p>{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/Debugging_HTML", "Learn/HTML/Introduction_to_HTML/Structuring_a_page_of_content", "Learn/HTML/Introduction_to_HTML")}}</p> + +<h2 id="本章目录">本章目录</h2> + +<ul> + <li><a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/Getting_started">开始学习 HTML</a></li> + <li><a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML">“头”里有什么?HTML 元信息</a></li> + <li><a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/HTML_text_fundamentals">HTML 文字处理初步</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks">创建超链接</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Advanced_text_formatting">高级文字格式</a></li> + <li><a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/文件和网站结构">文档和站点结构</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Debugging_HTML">HTML 调试</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Marking_up_a_letter">课程测验:为信件排版</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Structuring_a_page_of_content">课程测验:构建内容丰富的网页</a></li> +</ul> diff --git a/files/zh-cn/learn/html/introduction_to_html/structuring_a_page_of_content/index.html b/files/zh-cn/learn/html/introduction_to_html/structuring_a_page_of_content/index.html new file mode 100644 index 0000000000..934ad01b3c --- /dev/null +++ b/files/zh-cn/learn/html/introduction_to_html/structuring_a_page_of_content/index.html @@ -0,0 +1,104 @@ +--- +title: 构建内容丰富的网页 +slug: learn/HTML/Introduction_to_HTML/Structuring_a_page_of_content +tags: + - HTML + - 初学者 + - 布局 + - 结构 + - 设计 + - 评估 +translation_of: Learn/HTML/Introduction_to_HTML/Structuring_a_page_of_content +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenu("Learn/HTML/Introduction_to_HTML/Marking_up_a_letter", "Learn/HTML/Introduction_to_HTML")}}</div> + +<p class="summary">构建页面内容是一项重要技能,页面构建清晰才能顺利交付进行 CSS 布局。本测验将测试你是否能构思出页面的最终外观,以及是否会选用适当的结构语义。</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">预备知识:</th> + <td>完成本章之前的全部课程,特别是 <a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/文件和网站结构">文档和站点结构</a>。</td> + </tr> + <tr> + <th scope="row">学习目标:</th> + <td>测验网页结构知识和用标记呈现预期布局设计的方法。</td> + </tr> + </tbody> +</table> + +<h2 id="起点">起点</h2> + +<p>开始测验前,请先下载 <a class="external external-icon" href="https://raw.githubusercontent.com/roy-tian/learning-area/master/html/introduction-to-html/structuring-a-page-of-content-start/assets.zip">assets.zip</a>。其中包含:</p> + +<ul> + <li>需要补充结构标记的 HTML 文件。</li> + <li>给标记添加样式的 CSS 文件。</li> + <li>页面中使用的图片。</li> +</ul> + +<p>可在电脑上创建示例,也可以用 <a class="external external-icon" href="http://jsbin.com/">JSBin</a> 或 <a class="external external-icon" href="https://thimble.mozilla.org/">Thimble</a> 等网站来完成测验。</p> + +<h2 id="项目简介">项目简介</h2> + +<p>本项目的任务是为“观鸟网”的主页添加结构化的元素,使其可以进行布局设计。需要添加的有:</p> + +<ul> + <li>页眉(<code><header></code>),应充满页面宽度,并包含网站主标题、网站 logo 和导航栏菜单。样式生效后标题和 logo 应显示在在两边,导航栏在它们下方。</li> + <li>主内容区域(<code><main></code>),应有两栏,其中主区域显示欢迎信息,侧边栏包含一些缩略图。</li> + <li>页脚(<code><footer></code>),包含版权信息和鸣谢。</li> +</ul> + +<p>你应该为以下内容添加合适的标签:</p> + +<ul> + <li>页眉</li> + <li>导航菜单</li> + <li>主要内容</li> + <li>欢迎语</li> + <li>图片侧边栏</li> + <li>页脚</li> +</ul> + +<p>还应:</p> + +<ul> + <li>添加一个 {{htmlelement("link")}} 元素把现成的 CSS 文件引入页面。</li> +</ul> + +<h2 id="提示">提示</h2> + +<ul> + <li>可用 <a href="https://validator.w3.org/">W3C </a><a class="external external-icon" href="https://validator.w3.org/">HTML验证器</a> 来验证 HTML;验证通过有额外加分。(有两行包含 “googleapis” 的 <code><link></code> 元素用于从 Google Fonts 服务引入自定义字体到页面;它们不会被验证,所以不用担心。)</li> + <li>本测验不需要任何 CSS 知识;只需用 HTML 元素添加现成的 CSS 即可。</li> + <li>现成的 CSS 已经设计好布局,使用正确的结构元素,页面就会渲染成绿色。</li> + <li>如果你遇到困难不知道应该把添加元素到哪里,通常一个好的做法是:画一个简单的页面布局模块图,然后为每个块记录下恰当的元素。</li> +</ul> + +<h2 id="示例">示例</h2> + +<p>以下截图展示了添加标记后主页可能的外观:(可 <a class="external external-icon" href="https://roy-tian.github.io/learning-area/html/introduction-to-html/structuring-a-page-of-content-finished/">在线查看</a>)</p> + +<p><img alt="测试示例。一个简单的“观鸟网”主页,由页眉、页脚、欢迎信息、收藏照片等部分组成。" src="https://mdn.mozillademos.org/files/16540/bird-watching.png" style="display: block; margin: 0px auto;"></p> + +<h2 id="测验">测验</h2> + +<p>如果你是在课堂上进行这个测验,你可以把作品交给导师或教授去打分了。如果你是在自学,也可以在 <a href="https://discourse.mozilla.org/t/structuring-a-page-of-content-assignment/24678">本节测验的讨论页</a> 或者 <a href="https://wiki.mozilla.org/IRC">Mozilla 聊天室 </a>的 <a href="irc://irc.mozilla.org/mdn">#mdn</a> 频道取得帮助。要自己先尝试,作弊是不会有收获的!</p> + +<p>{{PreviousMenu("Learn/HTML/Introduction_to_HTML/Marking_up_a_letter", "Learn/HTML/Introduction_to_HTML")}}</p> + +<h2 id="本章目录">本章目录</h2> + +<ul> + <li><a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/Getting_started">开始学习 HTML</a></li> + <li><a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML">“头”里有什么?HTML 元信息</a></li> + <li><a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/HTML_text_fundamentals">HTML 文字处理初步</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks">创建超链接</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Advanced_text_formatting">高级文字格式</a></li> + <li><a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/文件和网站结构">文档和站点结构</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Debugging_HTML">HTML 调试</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Marking_up_a_letter">课程测验:为信件排版</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Structuring_a_page_of_content">课程测验:构建内容丰富的网页</a></li> +</ul> diff --git a/files/zh-cn/learn/html/introduction_to_html/the_head_metadata_in_html/index.html b/files/zh-cn/learn/html/introduction_to_html/the_head_metadata_in_html/index.html new file mode 100644 index 0000000000..e61085147b --- /dev/null +++ b/files/zh-cn/learn/html/introduction_to_html/the_head_metadata_in_html/index.html @@ -0,0 +1,287 @@ +--- +title: <head>标签里有什么? Metadata-HTML中的元数据 +slug: learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML +tags: + - HTML + - metadata + - 元数据 + - 教程 +translation_of: Learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/Getting_started", "Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals", "Learn/HTML/Introduction_to_HTML")}}</div> + +<p class="summary">在页面加载完成的时候,标签{{glossary("Head", "head")}}里的内容,是不会在页面中显示出来的。它包含了像页面的{{htmlelement("title")}}(标题) ,{{glossary("CSS")}}(如果你选择用 CSS 来为 HTML 内容添加样式),指向自定义图标的链接和其他的元数据(描述HTML的数据,比如,作者,和描述文档的重要关键词)。本文将涵盖上述内容并拓展,为您对标记的使用打下一个良好的基础。</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">预备知识:</th> + <td>初步了解 HTML(参见 <a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Getting_started">开始学习 HTML</a>)。</td> + </tr> + <tr> + <th scope="row">学习目标:</th> + <td>学习 HTML <head> 标签的概念、用途、基本组成,以及它对 HTML 文档所起的作用。</td> + </tr> + </tbody> +</table> + +<h2 id="什么是_HTML_头部元素">什么是 HTML 头部元素?</h2> + +<p>让我们简单回顾一下 <a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Getting_started#%E5%89%96%E6%9E%90HTML%E6%96%87%E6%A1%A3">上一章节的 HTML 文档</a>:</p> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>我的测试站点</title> + </head> + <body> + <p>这是我的页面</p> + </body> +</html></pre> + +<p>HTML {{htmlelement("head")}} 元素与 {{htmlelement("body")}} 元素不同,它的内容不会在浏览器中显示,它的作用是保存页面的一些 {{glossary("Metadata", "元数据")}}。上述示例 head 元素非常简短:</p> + +<pre class="brush: html notranslate"><head> + <meta charset="utf-8"> + <title>我的测试站点</title> +</head></pre> + +<p>然而大型页面的 head 会包含很多元数据。可以用 <a href="/zh-CN/docs/Learn/Discover_browser_developer_tools">开发者工具</a> 查看网页的 head 信息。本节并不打算面面俱到地讲述 head ,只是初步介绍几项 head 中重要的常用元素,让我们开始吧。</p> + +<h2 id="添加标题">添加标题</h2> + +<p>之前已经讲过 {{htmlelement("title")}},它可以为文档添加标题。别和 {{htmlelement("h1")}} 元素搞混了,{{htmlelement("h1")}} 是为 body 添加标题的。有时候 {{htmlelement("h1")}} 也叫作网页标题。但是二者并不相同。</p> + +<ul> + <li>{{htmlelement("h1")}} 元素在页面加载完毕时显示在页面中,通常只出现一次,用来标记页面内容的标题(故事名称、新闻摘要,等等)。</li> + <li>{{htmlelement("title")}} 元素是一项元数据,用于表示整个 HTML 文档的标题(而不是文档内容)。</li> +</ul> + +<h3 id="主动学习:一个简单的示例">主动学习:一个简单的示例</h3> + +<ol> + <li>为了开始这个交互式学习,我们希望你到我们的 Github 库中下载一份我们的 <a href="https://github.com/roy-tian/learning-area/blob/master/html/introduction-to-html/the-html-head/title-example.html">title-example.html 网页</a>。要做到这一点,你可以选择下面两种操作之一 + + <ol> + <li>使用你的代码编辑器,从页面中拷贝粘贴代码到一个新的文本文件中,然后将其保存到一个适当的地方。</li> + <li>按下页面中的 "Raw" 按钮, 从浏览器的菜单中选择 文件<em>> 另存网页为...</em> , 然后选择一个地方来保存这个文件。</li> + </ol> + </li> + <li>在浏览器中打开文件,你会看到类似这样效果: + <p><img alt="A simple web page with the title set to <title> element, and the <h1> set to <h1> element." src="https://mdn.mozillademos.org/files/17388/%E6%A0%87%E9%A2%98%E7%A4%BA%E4%BE%8B.png" style="display: block; height: 393px; margin: 0px auto; width: 650px;">现在很明显的可以看到 <code><h1></code> 出现的地方,和 <code><title></code> 出现的地方!</p> + </li> + <li>你应该尝试着在你的代码编辑器中打开这些代码,编辑这些元素的内容,然后在你的浏览器中刷新页面。祝你玩得开心。</li> +</ol> + +<p>元素 <code><title></code> 也被以其他的方式使用着。 比如说,如果你尝试为某个页面添加书签,(在火狐浏览器中点击地址栏末尾的星标),你会看到 <code><title></code> 的内容被作为建议的书签名。</p> + +<p><img alt="Firefox 中将网页添加为书签。书签名根据 <title> 元素自动生成。" src="https://mdn.mozillademos.org/files/17389/%E4%B9%A6%E7%AD%BE%E7%A4%BA%E4%BE%8B.png" style="display: block; height: 497px; margin: 0px auto; width: 650px;"></p> + +<p>元素 <code><title></code> 的内容也被用在搜索的结果中,正如你即将在下面看到的。</p> + +<h2 id="元数据:<meta>元素">元数据:<meta>元素</h2> + +<p>元数据就是描述数据的数据,而HTML有一个“官方的”方式来为一个文档添加元数据—— {{htmlelement("meta")}} 元素。当然,其他在这篇文章中提到的东西也可以被当作元数据。有很多不同种类的 <code><meta></code> 元素可以被包含进你的页面的<head>元素,但是现在我们还不会尝试去解释所有类型,这只会引起混乱。我们会解释一些你常会看到的类型,先让你有个概念。</p> + +<h3 id="指定你的文档中字符的编码">指定你的文档中字符的编码</h3> + +<p>在上面的例子中,这行是被包含的:</p> + +<pre class="brush: html notranslate"><meta charset="utf-8"></pre> + +<p>这个元素简单的指定了文档的字符编码 —— 在这个文档中被允许使用的字符集。 <code>utf-8</code> 是一个通用的字符集,它包含了任何人类语言中的大部分的字符。 意味着该 web 页面可以显示任意的语言;所以对于你的每一个页面都使用这个设置会是一个好主意!比如说,你的页面可以很好的处理中文和藏文:</p> + +<p><img alt="同时包含中文和藏文的网页。将页面编码设置为utf8后,两种语言均可正常显示。" src="https://mdn.mozillademos.org/files/17390/%E7%BC%96%E7%A0%81%E6%AD%A3%E7%A1%AE.png" style="display: block; height: 329px; margin: 0px auto; width: 650px;">比如说,如果你将你的字符集设置为 <code>GBK</code> (中国大陆国标字符集),那么页面将出现乱码:</p> + +<p><img alt="同时包含中文和藏文的网页。将页面编码设置为gbk后,藏语无法正常显示。" src="https://mdn.mozillademos.org/files/17391/%E7%BC%96%E7%A0%81%E9%94%99%E8%AF%AF.png" style="display: block; height: 318px; margin: 0px auto; width: 650px;"></p> + +<div class="note"> +<p><strong>注</strong>: 一些浏览器(比如Chrome)会自动修正错误的编码,所以取决于你所使用的浏览器,你或许不会看到这个问题。无论如何,你仍然应该为你的页面手动设置编码为<code>utf-8</code>,来避免在其他浏览器中可能出现的潜在问题。</p> +</div> + +<h3 id="交互式学习:_体验字符集">交互式学习: 体验字符集</h3> + +<p>为了进行这个练习,回到你在前面<title>章节中获取的HTML模板 (<a href="https://github.com/roy-tian/learning-area/blob/master/html/introduction-to-html/the-html-head/title-example.html">title-example.html 网页</a>),试着改变其字符集的值为<code>GBK</code>,然后将藏语添加到页面中。这就是我们使用的代码:</p> + +<pre class="brush: html notranslate"><p>藏语示例:བཀྲ་ཤིས་བདེ་ལེགས།</p></pre> + +<h3 id="添加作者和描述">添加作者和描述</h3> + +<p>许多<code><meta></code> 元素包含了<code>name</code> 和 <code>content</code> 特性:</p> + +<ul> + <li><code>name</code> 指定了meta 元素的类型; 说明该元素包含了什么类型的信息。</li> + <li><code>content</code> 指定了实际的元数据内容。</li> +</ul> + +<p>这两个meta 元素对于定义你的页面的作者和提供页面的简要描述是很有用的 。让我们看一个例子:</p> + +<pre class="brush: html notranslate"><meta name="author" content="Chris Mills"> +<meta name="description" content="The MDN Learning Area aims to provide +complete beginners to the Web with all they need to know to get +started with developing web sites and applications."></pre> + +<p>指定作者在某些情况下是很有用的:如果你需要联系页面的作者,问一些关于页面内容的问题。 一些内容管理系统能够自动获取页面作者的信息,然后用于某些用途。</p> + +<p>指定包含关于页面内容的关键字的页面内容的描述是很有用的,因为它可能或让你的页面在搜索引擎的相关的搜索出现得更多 (这些行为术语上被称为 <a href="/zh-CN/docs/Glossary/SEO">Search Engine Optimization</a>, or {{glossary("SEO")}}.)</p> + +<h3 id="实践操作_在搜索引擎中description的使用">实践操作: 在搜索引擎中description的使用</h3> + +<p>description也被使用在搜索引擎显示的结果页中。下面通过一个例子来说明</p> + +<ol> + <li>访问 <a href="https://developer.mozilla.org/zh-CN/">MDN Web Docs</a>。</li> + <li>查看网页源代码(<em>通过鼠标右键点击网页在弹出的菜单中选择[查看网页源代码]</em>)</li> + <li>找到description的meta标签。就和如下展示的这样: + <pre class="brush: html notranslate"><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."></pre> + </li> + <li>现在,在你喜欢的搜索引擎里搜索“MDN Web Docs” (下图展示的是在谷歌搜索里的情况) 。你会看到description <code><meta></code> and <code><title></code> 元素如何在搜索结果里显示— 很值得这样做哦!</li> +</ol> + +<p><img alt='A Google search result for "MDN Web Docs"' src="https://mdn.mozillademos.org/files/16074/mdn-search-result.png" style="height: 982px; width: 1302px;"></p> + +<div class="note"> +<p><strong>Note</strong>:在谷歌搜索里,在主页面链接下面,你将看到一些相关子页面 — 这些是站点链接,可以在 <a href="http://www.google.com/webmasters/tools/">Google's webmaster tools</a> 配置— 一种可以使你的站点对搜索引擎更友好的方式。</p> +</div> + +<div class="note"> +<p><strong>Note</strong>: 许多 <code><meta></code> 特性已经不再使用。 例如,keyword <code><meta></code> 元素(<code><meta name="keywords" content="fill, in, your, keywords, here"></code>)— 提供关键词给搜索引擎,根据不同的搜索词,查找到相关的网站 — 已经被搜索引擎忽略了, 因为作弊者填充了大量关键词到keyword, 错误地引导搜索结果。</p> +</div> + +<h3 id="其他类型的元数据">其他类型的元数据</h3> + +<p>当你在网站上查看源码时,你也会发现其他类型的元数据。你在网站上看到的许多功能都是专有创作,旨在向某些网站(如社交网站)提供可使用的特定信息。</p> + +<p>例如,Facebook 编写的元数据协议 <a href="http://ogp.me/">Open Graph Data</a> 为网站提供了更丰富的元数据。在 MDN 源代码中,你会发现:</p> + +<pre class="brush: html notranslate"><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"></pre> + +<p>上面代码展现的一个效果就是,当你在 Facebook 上链接到 MDN 时,该链接将显示一个图像和描述:这为用户提供更丰富的体验。</p> + +<p><img alt="Open graph protocol data from the MDN homepage as displayed on facebook, showing an image, title, and description." src="https://mdn.mozillademos.org/files/12349/facebook-output.png" style="display: block; margin: 0 auto;">Twitter 还拥有自己的类型的专有元数据协议,当网站的 URL 显示在 twitter.com 上时,它具有相似的效果。例如下面:</p> + +<pre class="brush: html notranslate"><meta name="twitter:title" content="Mozilla Developer Network"></pre> + +<h2 id="在你的站点增加自定义图标">在你的站点增加自定义图标</h2> + +<p>为了进一步丰富你的网站设计,你可以在元数据中添加对自定义图标的引用,这些将在特定的场合中显示。</p> + +<p>这个不起眼的图标已经存在很多很多年了,16 x 16 像素是这种图标的第一种类型。你可以看见这些图标出现在浏览器每一个打开的页面中的标签页中中以及在书签面板中的书签页面中。</p> + +<p>页面添加图标的方式有:</p> + +<ol> + <li>将其保存在与网站的索引页面相同的目录中,以.ico格式保存(大多数浏览器将支持更通用的格式,如.gif或.png,但使用ICO格式将确保它能在如Internet Explorer 6一样久远的浏览器显示)</li> + <li>将以下行添加到HTML <head>中以引用它: + <pre class="brush: html notranslate"><link rel="shortcut icon" href="favicon.ico" type="image/x-icon"></pre> + </li> +</ol> + +<p>现代浏览器在各种场合使用favicons,如打开的页面标签页和书签面板中的书签页面。下面是一个favicon 出现在书签面板中的例子:<img alt="The Firefox bookmarks panel, showing a bookmarked example with a favicon displayed next to it." src="https://mdn.mozillademos.org/files/12351/bookmark-favicon.png" style="display: block; margin: 0 auto;"></p> + +<p>如今还有很多其他的图标类型可以考虑。 例如,你可以在 MDN 主页的源代码中找到它:</p> + +<pre class="brush: html notranslate"><!-- third-generation iPad with high-resolution Retina display: --> +<link rel="apple-touch-icon-precomposed" sizes="144x144" href="https://developer.cdn.mozilla.net/static/img/favicon144.a6e4162070f4.png"> +<!-- iPhone with high-resolution Retina display: --> +<link rel="apple-touch-icon-precomposed" sizes="114x114" href="https://developer.cdn.mozilla.net/static/img/favicon114.0e9fabd44f85.png"> +<!-- first- and second-generation iPad: --> +<link rel="apple-touch-icon-precomposed" sizes="72x72" href="https://developer.cdn.mozilla.net/static/img/favicon72.8ff9d87c82a0.png"> +<!-- non-Retina iPhone, iPod Touch, and Android 2.1+ devices: --> +<link rel="apple-touch-icon-precomposed" href="https://developer.cdn.mozilla.net/static/img/favicon57.a2490b9a2d76.png"> +<!-- basic favicon --> +<link rel="shortcut icon" href="https://developer.cdn.mozilla.net/static/img/favicon32.e02854fdcf73.png"></pre> + +<p>这些注释解释了每个图标的用途 - 这些元素涵盖的东西提供一个高分辨率图标,这些高分辨率图标当网站保存到iPad的主屏幕时使用。</p> + +<p>不用担心现在实现所有这些类型的图标 - 这是一个相当先进的功能,你将不会被要求在这个课堂上学习这个知识点。 这里的主要目的是让你提前了解有这一样东西以防当你浏览其他网站的源代码时不理解源代码的含义。</p> + +<ul> +</ul> + +<div class="note"> +<p><strong>注</strong>:如果你的网站使用了内容安全策略(Content Security Policy, CSP)来增加安全性,这个策略会应用在图标上。如果你遇到了图标没有被加载的问题,你需要确认认 {{HTTPHeader("Content-Security-Policy")}} header的 <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/img-src"><code>img-src</code> directive</a> 没有禁止访问图标。</p> +</div> + +<h2 id="在HTML中应用CSS和JavaScript">在HTML中应用CSS和JavaScript</h2> + +<p>如今,几乎你使用的所有网站都会使用 {{glossary("CSS")}} 让网页更加炫酷,使用{{glossary("JavaScript")}}让网页有交互功能,比如视频播放器,地图,游戏以及更多功能。这些应用在网页中很常见,它们分别使用 {{htmlelement("link")}}元素以及 {{htmlelement("script")}} 元素。</p> + +<ul> + <li> + <p> {{htmlelement("link")}} 元素经常位于文档的头部。这个link元素有2个属性,rel="stylesheet"表明这是文档的样式表,而 href包含了样式表文件的路径:</p> + + <pre class="brush: html notranslate"><link rel="stylesheet" href="my-css-file.css"></pre> + </li> + <li> + <p>{{htmlelement("script")}} 部分没必要非要放在文档头部;实际上,把它放在文档的尾部(在 <code></body>标签之前</code>)是一个更好的选择,这样可以确保在加载脚本之前浏览器已经解析了HTML内容(如果脚本加载某个不存在的元素,浏览器会报错)。</p> + + <pre class="brush: html notranslate"><script src="my-js-file.js"></script></pre> + + <p><strong>注意:</strong> <code><script></code>元素看起来像一个空元素,但它并不是,因此需要一个结束标记。您还可以选择将脚本放入<code><script></code>元素中,而不是指向外部脚本文件。</p> + </li> +</ul> + +<h3 id="实践操作_在网页中应用CSS和JavaScript">实践操作: 在网页中应用CSS和JavaScript</h3> + +<ol> + <li>开始操作之前,先拷贝我们的 <a href="https://github.com/roy-tian/learning-area/blob/master/html/introduction-to-html/the-html-head/meta-example.html">meta-example.html</a>, <a href="https://github.com/roy-tian/learning-area/blob/master/html/introduction-to-html/the-html-head/script.js">script.js</a> 和 <a href="https://github.com/roy-tian/learning-area/blob/master/html/introduction-to-html/the-html-head/style.css">style.css</a> 文件,并把它们保存到本地电脑的同一目录下,确保使用了正确的文件名和文件格式。</li> + <li>使用浏览器和文字编辑器同时打开你的HTML文件。</li> + <li>根据上面的信息,添加 {{htmlelement("link")}}和 {{htmlelement("script")}}部分到您的HTML文件中, 这样你的HTML就可以应用CSS和JavaScript了。</li> +</ol> + +<p>如果按照上述步骤正确地执行, 当你保存HTML文件并重新刷新浏览器的话,你会发现页面已经变样了:</p> + +<p><img alt="包含 JS/CSS的网页示例。CSS将页面背景设置为绿色,由JS向页面添加一个动态列表。" src="https://mdn.mozillademos.org/files/17392/JS_CSS_%E7%A4%BA%E4%BE%8B.png" style="display: block; height: 471px; margin: 0px auto; width: 650px;"></p> + +<ul> + <li>JavaScript在页面中添加了一个空列表。现在当你点击列表中的任何地方,浏览器会弹出一个对话框要求你为新列表项输入一些文本内容。当你点击OK按钮,刚刚那个新的列表项会添加到页面上,当你点击那些已有的列表项,会弹出一个对话框允许你修改列表项的文本。</li> + <li>CSS使页面背景变成了绿色,文本变得大了一点。它还将JavaScript添加到页面中的一些内容进行了样式化,(带有黑色边框的红色条是CSS添加到js生成的列表中的样式。)</li> +</ul> + +<div class="note"> +<p><strong>注意</strong>:如果你卡在这个练习当中,无法正常应用CSS和JavaScript,试着查看一下我们的 <a href="https://github.com/roy-tian/learning-area/blob/master/html/introduction-to-html/the-html-head/css-and-js.html">css-and-js.html</a> 页面实例。</p> +</div> + +<h2 id="为文档设定主语言">为文档设定主语言</h2> + +<p>最后,值得一提的是可以(而且有必要)为站点设定语言, 这个可以通过添加<code>lang</code>属性到HTML开始标签中来实现 (参考 <a href="https://github.com/roy-tian/learning-area/blob/master/html/introduction-to-html/the-html-head/meta-example.html">meta-example.html</a>),如下所示:</p> + +<pre class="brush: html notranslate"><html lang="zh-CN"></pre> + +<p>这在很多方面都很有用。如果你的HTML文档的语言设置好了,那么你的HTML文档就会被搜索引擎更有效地索引 (例如,允许它在特定于语言的结果中正确显示),对于那些使用屏幕阅读器的视障人士也很有用(比如, 法语和英语中都有“six”这个单词,但是发音却完全不同)。</p> + +<p>你还可以将文档的分段设置为不同的语言。例如,我们可以把日语部分设置为日语,如下所示:</p> + +<pre class="brush: html notranslate"><p>日语实例: <span lang="jp">ご飯が熱い。</span>.</p></pre> + +<p>这些codes是根据 <a href="https://en.wikipedia.org/wiki/ISO_639-1">ISO 639-1</a> 标准定义的。你可以在<a href="https://www.w3.org/International/articles/language-tags/">Language tags in HTML and XML</a>找到更多相关的。</p> + +<h2 id="总结">总结</h2> + +<p>已经到了我们快速学习HTML head的尾声 — 你还能学到更多的相关的,但是现阶段详尽的讲的太多会无聊且迷惑, 我们只希望你现在在这学到最基本的概念! 下一篇我们将要学习 HTML 文本基础。</p> + +<p>{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/Getting_started", "Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals", "Learn/HTML/Introduction_to_HTML")}}</p> + +<h2 id="本章目录">本章目录</h2> + +<ul> + <li><a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/Getting_started">开始学习 HTML</a></li> + <li><a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML">“头”里有什么?HTML 元信息</a></li> + <li><a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/HTML_text_fundamentals">HTML 文字处理初步</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks">创建超链接</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Advanced_text_formatting">高级文字格式</a></li> + <li><a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/文件和网站结构">文档和站点结构</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Debugging_HTML">HTML 调试</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Marking_up_a_letter">课程测验:为信件排版</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Structuring_a_page_of_content">课程测验:构建内容丰富的网页</a></li> +</ul> diff --git a/files/zh-cn/learn/html/introduction_to_html/文件和网站结构/index.html b/files/zh-cn/learn/html/introduction_to_html/文件和网站结构/index.html new file mode 100644 index 0000000000..63c421487b --- /dev/null +++ b/files/zh-cn/learn/html/introduction_to_html/文件和网站结构/index.html @@ -0,0 +1,252 @@ +--- +title: 文档与网站架构 +slug: learn/HTML/Introduction_to_HTML/文件和网站结构 +tags: + - HTML + - 块 + - 教程 + - 新手 + - 样式 + - 站点 + - 脚本编写 + - 页面 +translation_of: Learn/HTML/Introduction_to_HTML/Document_and_website_structure +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/Advanced_text_formatting", "Learn/HTML/Introduction_to_HTML/Debugging_HTML", "Learn/HTML/Introduction_to_HTML")}}</div> + +<p class="summary">{{glossary("HTML")}} 不仅能够定义网页的单独部分(例如“段落”或“图片”),还可以使用块级元素(例如“标题栏”、“导航菜单”、“主内容列”)来定义网站中的复合区域。本文将探讨如何规划基本的网站结构,并根据规划的结构来编写 HTML。</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">预备知识:</th> + <td>阅读 <a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Getting_started">开始学习 HTML</a>、<a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals">HTML 文字处理初步</a> 、<a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks">创建超链接</a>,掌握相关基础知识。</td> + </tr> + <tr> + <th scope="row">学习目标:</th> + <td>会用语义标签来构建文档,会搭建简单的网站结构。</td> + </tr> + </tbody> +</table> + +<h2 id="文档的基本组成部分">文档的基本组成部分</h2> + +<p>网页的外观多种多样,但是除了全屏视频或游戏,或艺术作品页面,或只是结构不当的页面以外,都倾向于使用类似的标准组件:</p> + +<dl> + <dt>页眉</dt> + <dd>通常横跨于整个页面顶部有一个大标题 和/或 一个标志。 这是网站的主要一般信息,通常存在于所有网页。</dd> + <dt>导航栏</dt> + <dd>指向网站各个主要区段的超链接。通常用菜单按钮、链接或标签页表示。类似于标题栏,导航栏通常应在所有网页之间保持一致,否则会让用户感到疑惑,甚至无所适从。许多 web 设计人员认为导航栏是标题栏的一部分,而不是独立的组件,但这并非绝对;还有人认为,两者独立可以提供更好的 <a href="/zh-CN/docs/learn/Accessibility">无障碍访问特性</a>,因为屏幕阅读器可以更清晰地分辨二者。</dd> + <dt>主内容</dt> + <dd>中心的大部分区域是当前网页大多数的独有内容,例如视频、文章、地图、新闻等。这些内容是网站的一部分,且会因页面而异。</dd> + <dt>侧边栏</dt> + <dd>一些外围信息、链接、引用、广告等。通常与主内容相关(例如一个新闻页面上,侧边栏可能包含作者信息或相关文章链接),还可能存在其他的重复元素,如辅助导航系统。</dd> + <dt>页脚</dt> + <dd>横跨页面底部的狭长区域。和标题一样,页脚是放置公共信息(比如版权声明或联系方式)的,一般使用较小字体,且通常为次要内容。 还可以通过提供快速访问链接来进行 {{Glossary("SEO")}}。</dd> +</dl> + +<p>一个“典型的网站”可能会这样布局:</p> + +<p><img alt="一个简单站点首页截图" src="https://mdn.mozillademos.org/files/16497/snapshot.png" style="display: block; margin: 0px auto;"></p> + +<h2 id="用于构建内容的_HTML">用于构建内容的 HTML</h2> + +<p>以上简单示例不是很精美,但是足够说明网站的典型布局方式了。 一些站点拥有更多列,其中一些远比这复杂,但一切在你掌握之中。通过合适的CSS, 你可以使用相当多种的任意页面元素来环绕在不同的页面区域来做成你想要的样子,但如前所述,我们要敬畏语义,做到<strong>正确选用元素</strong>。</p> + +<p>这是因为视觉效果并不是一切。 我们可以修改最重要内容(例如导航菜单和相关链接)的颜色、字体大小来吸引用户的注意,但是这对视障人士是无效的,“粉红色”和“大字体”对他们并不奏效。</p> + +<div class="note"> +<p><strong>注:</strong><a href="http://www.color-blindness.com/2006/04/28/colorblind-population/">全球色盲患者比例为 4%</a>,换句话说,每 12 名男性就有一位色盲,每 200 名女性就有一位色盲。全盲和视障人士约占世界人口(<a href="https://en.wikipedia.org/wiki/World_human_population#/media/File:World_population_history.svg">约 70 亿</a>)的 13%(2015年 <a href="https://en.wikipedia.org/wiki/Visual_impairment">全球约有 9.4 亿人口存在视力问题</a>)。</p> +</div> + +<p>HTML 代码中可根据功能来为区段添加标记。可使用元素来无歧义地表示上文所讲的内容区段,屏幕阅读器等辅助技术可以识别这些元素,并帮助执行“找到主导航 “或”找到主内容“等任务。参见前文所讲的 <a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/HTML_text_fundamentals#为什么我们需要结构化">页面中元素结构和语义不佳所带来的后果</a>。</p> + +<p>为了实现语义化标记,HTML 提供了明确这些区段的专用标签,例如:</p> + +<ul> + <li>{{htmlelement("header")}}:页眉。</li> + <li>{{htmlelement("nav")}}:导航栏。</li> + <li>{{htmlelement("main")}}:主内容。主内容中还可以有各种子内容区段,可用{{HTMLElement("article")}}、{{htmlelement("section")}} 和 {{htmlelement("div")}} 等元素表示。</li> + <li>{{htmlelement("aside")}}:侧边栏,经常嵌套在 {{htmlelement("main")}} 中。</li> + <li>{{htmlelement("footer")}}:页脚。</li> +</ul> + +<h3 id="主动学习:研究示例代码">主动学习:研究示例代码</h3> + +<p>上图的示例可用下面的代码表示(完整代码请参见 <a href="https://github.com/roy-tian/learning-area/blob/master/html/introduction-to-html/document-and-website-structure/index.html">GitHub</a>),请结合图片观察代码,并找出代码中可见的区段:</p> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>二次元俱乐部</title> + <link href="https://fonts.googleapis.com/css?family=Open+Sans+Condensed:300|Sonsie+One" rel="stylesheet"> + <link href="https://fonts.googleapis.com/css?family=ZCOOL+KuaiLe" rel="stylesheet"> + <link href="style.css" rel="stylesheet"> + </head> + + <body> + <header> <!-- 本站所有网页的统一主标题 --> + <h1>聆听电子天籁之音</h1> + </header> + + <nav> <!-- 本站统一的导航栏 --> + <ul> + <li><a href="#">主页</a></li> + <!-- 共n个导航栏项目,省略…… --> + </ul> + + <form> <!-- 搜索栏是站点内导航的一个非线性的方式。 --> + <input type="search" name="q" placeholder="要搜索的内容"> + <input type="submit" value="搜索"> + </form> + </nav> + + <main> <!-- 网页主体内容 --> + <article> + <!-- 此处包含一个 article(一篇文章),内容略…… --> + </article> + + <aside> <!-- 侧边栏在主内容右侧 --> + <h2>相关链接</h2> + <ul> + <li><a href="#">这是一个超链接</a></li> + <!-- 侧边栏有n个超链接,略略略…… --> + </ul> + </aside> + </main> + + <footer> <!-- 本站所有网页的统一页脚 --> + <p>© 2050 某某保留所有权利</p> + </footer> + </body> +</html></pre> + +<p>请花一些时间来阅读,其中的注释应该能够帮助你理解这些代码。现在能够理解上面的代码就可以,因为编写一套正确的 HTML 结构是理解文档布局的前提,布局工作就交给 CSS 吧。在学习 CSS 一章时我们再展开介绍。</p> + +<h2 id="HTML_布局元素细节">HTML 布局元素细节</h2> + +<p>理解所有 HTML 区段元素具体含义是很有益处的,这一点将随着个人 web 开发经验的逐渐丰富日趋显现。更多细节请查阅 <a href="/zh-CN/docs/Web/HTML/Element">HTML 元素参考</a>。现在,你只需要理解以下主要元素的意义:</p> + +<ul> + <li>{{HTMLElement('main')}} 存放每个页面独有的内容。每个页面上只能用一次 <code><main></code>,且直接位于 {{HTMLElement('body')}} 中。最好不要把它嵌套进其它元素。</li> + <li>{{HTMLElement('article')}} 包围的内容即一篇文章,与页面其它部分无关(比如一篇博文)。</li> + <li>{{HTMLElement('section')}} 与 <code><article></code> 类似,但 <code><section></code> 更适用于组织页面使其按功能(比如迷你地图、一组文章标题和摘要)分块。一般的最佳用法是:以 <a href="https://developer.mozilla.org/en-US/Learn/HTML/Howto/Set_up_a_proper_title_hierarchy">标题</a> 作为开头;也可以把一篇 <code><article></code> 分成若干部分并分别置于不同的 <code><section></code> 中,也可以把一个区段 <code><section></code> 分成若干部分并分别置于不同的 <code><article></code> 中,取决于上下文。</li> + <li>{{HTMLElement('aside')}} 包含一些间接信息(术语条目、作者简介、相关链接,等等)。</li> + <li>{{HTMLElement('header')}} 是简介形式的内容。如果它是 {{HTMLElement('body')}} 的子元素,那么就是网站的全局页眉。如果它是 {{HTMLElement('article')}} 或{{HTMLElement('section')}} 的子元素,那么它是这些部分特有的页眉(此 <code><header></code> 非彼 <a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML#增加一个标题">标题</a>)。</li> + <li>{{HTMLElement('nav')}} 包含页面主导航功能。其中不应包含二级链接等内容。</li> + <li>{{HTMLElement('footer')}} 包含了页面的页脚部分。</li> +</ul> + +<h3 id="无语义元素">无语义元素</h3> + +<p>有时你会发现,对于一些要组织的项目或要包装的内容,现有的语义元素均不能很好对应。有时候你可能只想将一组元素作为一个单独的实体来修饰来响应单一的用 {{glossary("CSS")}} 或 {{glossary("JavaScript")}}。为了应对这种情况,HTML提供了 {{HTMLElement("div")}} 和 {{HTMLElement("span")}} 元素。应配合使用 {{htmlattrxref('class')}} 属性提供一些标签,使这些元素能易于查询。</p> + +<p>{{HTMLElement("span")}} 是一个内联的(inline)无语义元素,最好只用于无法找到更好的语义元素来包含内容时,或者不想增加特定的含义时。例如:</p> + +<pre class="brush: html notranslate"><p>国王喝得酩酊大醉,在凌晨 1 点时才回到自己的房间,踉跄地走过门口。<span class="editor-note">[编辑批注:此刻舞台灯光应变暗]</span>.</p></pre> + +<p>这里,“编辑批注”仅仅是对舞台剧导演提供额外指引;没有具体语义。对于视力正常的用户,CSS 应将批注内容与主内容稍微隔开一些。</p> + +<p>{{HTMLElement("div")}} 是一个块级无语义元素,应仅用于找不到更好的块级元素时,或者不想增加特定的意义时。例如,一个电子商务网站页面上有一个一直显示的购物车组件。</p> + +<pre class="brush: html notranslate"><div class="shopping-cart"> + <h2>购物车</h2> + <ul> + <li> + <p><a href=""><strong>银耳环</strong></a>:$99.95.</p> + <img src="../products/3333-0985/" alt="Silver earrings"> + </li> + <li> + ... + </li> + </ul> + <p>售价:$237.89</p> +</div></pre> + +<p>这里不应使用 <code><aside></code>,因为它和主内容并没有必要的联系(你想在任何地方都能看到它)。甚至不能用 <code><section></code> ,因为它也不是页面上主内容的一部分。所以在这种情况下就应使用 <code><div></code>,为满足无障碍使用特征,还应为购物车的标题设置一个可读标签。</p> + +<div class="warning"> +<p><strong>警告:</strong><code><div></code> 非常便利但容易被滥用。由于它们没有语义值,会使 HTML 代码变得混乱。要小心使用,只有在没有更好的语义方案时才选择它,而且要尽可能少用, 否则文档的升级和维护工作会非常困难。</p> +</div> + +<h3 id="换行与水平分割线">换行与水平分割线</h3> + +<p>有时会用到 {{htmlelement("br")}} 和 {{htmlelement("hr")}} 两个元素,需要介绍一下。</p> + +<p><code><br></code> 可在段落中进行换行;<code><br></code> 是唯一能够生成多个短行结构(例如邮寄地址或诗歌)的元素。比如:</p> + +<pre class="brush: html notranslate"><p>从前有个人叫小高<br> +他说写 HTML 感觉最好<br> +但他写的代码结构语义一团糟<br> +他写的标签谁也懂不了。</p> +</pre> + +<p>没有 <code><br></code> 元素,这段会直接显示在长长的一行中(如前文所讲,<a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/Getting_started#HTML中的空白">HTML会忽略大部分空格</a>);使用 <code><br></code> 元素,才使得诗看上去像诗:</p> + +<p>从前有个人叫小高<br> + 他说写 HTML 感觉最好<br> + 但他写的代码结构语义一团糟<br> + 他写的标签谁也懂不了。</p> + +<p><code><hr></code> 元素在文档中生成一条水平分割线,表示文本中主题的变化(例如话题或场景的改变)。一般就是一条水平的直线。例如:</p> + +<pre class="notranslate"><p>原来这唐僧是个慈悯的圣僧。他见行者哀告,却也回心转意道:“既如此说,且饶你这一次。再休无礼。如若仍前作恶,这咒语颠倒就念二十遍!”行者道:“三十遍也由你,只是我不打人了。”却才伏侍唐僧上马,又将摘来桃子奉上。唐僧在马上也吃了几个,权且充饥。</p> +<hr> +<p>却说那妖精,脱命升空。原来行者那一棒不曾打杀妖精,妖精出神去了。他在那云端里,咬牙切齿,暗恨行者道:“几年只闻得讲他手段,今日果然话不虚传。那唐僧已此不认得我,将要吃饭。若低头闻一闻儿,我就一把捞住,却不是我的人了。不期被他走来,弄破我这勾当,又几乎被他打了一棒。若饶了这个和尚,诚然是劳而无功也。我还下去戏他一戏。”</p></pre> + +<p>将渲染成:</p> + +<p>原来这唐僧是个慈悯的圣僧。他见行者哀告,却也回心转意道:“既如此说,且饶你这一次。再休无礼。如若仍前作恶,这咒语颠倒就念二十遍!”行者道:“三十遍也由你,只是我不打人了。”却才伏侍唐僧上马,又将摘来桃子奉上。唐僧在马上也吃了几个,权且充饥。</p> + +<hr> +<p>却说那妖精,脱命升空。原来行者那一棒不曾打杀妖精,妖精出神去了。他在那云端里,咬牙切齿,暗恨行者道:“几年只闻得讲他手段,今日果然话不虚传。那唐僧已此不认得我,将要吃饭。若低头闻一闻儿,我就一把捞住,却不是我的人了。不期被他走来,弄破我这勾当,又几乎被他打了一棒。若饶了这个和尚,诚然是劳而无功也。我还下去戏他一戏。”</p> + +<h2 id="规划一个简单的网站">规划一个简单的网站</h2> + +<p>在完成页面内容的规划后,一般应按部就班地规划整个网站的内容,要可能带给用户最好的体验,需要哪些页面、如何排列组合这些页面、如何互相链接等问题不可忽略。这些工作称为{{glossary("Information architecture", "信息架构")}}。在大型网站中,大多数规划工作都可以归结于此,而对于一个只有几个页面的简单网站,规划设计过程可以更简单,更有趣!</p> + +<ol> + <li>时刻记住,大多数(不是全部)页面会使用一些相同的元素,例如导航菜单以及页脚内容。若网站为商业站点,不妨在所有页面的页脚都加上联系方式。请记录这些对所有页面都通用的内容:<img alt="所有页面共有的内容,包括:站点标题、Logo、联系方式、版权声明、语言等信息。" src="https://mdn.mozillademos.org/files/16508/%E9%80%9A%E7%94%A8%E5%86%85%E5%AE%B9.gif" style="display: block; margin: 0px auto;"></li> + <li>接下来,可为页面结构绘制草图(这里与前文那个站点页面的截图类似)。记录每一块的作用:<img alt="简单的页面布局示意图,有页眉、页脚、主内容、侧边栏。" src="https://mdn.mozillademos.org/files/16509/%E9%A1%B5%E9%9D%A2%E5%B8%83%E5%B1%80.gif" style="display: block; margin: 0px auto;"></li> + <li>下面,对于期望添加进站点的所有其它(通用内容以外的)内容展开头脑风暴,直接罗列出来。<img alt="把假日旅行站点的所有功能罗列到一个列表中" src="https://mdn.mozillademos.org/files/16522/%E5%8A%9F%E8%83%BD%E5%88%97%E8%A1%A8.gif" style="display: block; margin: 0px auto;"></li> + <li>下一步,试着对这些内容进行分组,这样可以让你了解哪些内容可以放在同一个页面。这种做法和 {{glossary("Card sorting", "卡片分类法")}} 非常相似。<img alt="假日网站的页面应分5类:搜索、特别提供、具体国家信息、搜索结果、购物。" src="https://mdn.mozillademos.org/files/16521/%E5%8A%9F%E8%83%BD%E5%88%86%E7%B1%BB.gif" style="display: block; margin: 0px auto;"></li> + <li>接下来,试着绘制一个站点地图的草图,使用一个气泡代表网站的一个页面,并绘制连线来表示页面间的一般工作流。主页面一般置于中心,且链接到其他大多数页面;小型网站的大多数页面都可以从主页的导航栏中链接跳转。也可记录下内容的显示方式。<img alt="" src="https://mdn.mozillademos.org/files/16523/%E7%AB%99%E7%82%B9%E5%9C%B0%E5%9B%BE.gif" style="display: block; margin: 0px auto;"></li> +</ol> + +<h3 id="主动学习:创建站点地图">主动学习:创建站点地图</h3> + +<p>自己创造一个网站(什么网站呢?)并尝试执行上述步骤。</p> + +<div class="note"> +<p><strong>注:</strong>记得保存你的杰作,今后可能会用到哦。</p> +</div> + +<h2 id="小结">小结</h2> + +<p>现在你应该对如何构建网页/站点有了更好的理解。下一节我们将学习如何调试 HTML。</p> + +<h2 id="另请参阅">另请参阅</h2> + +<ul> + <li><a href="/en-US/docs/Web/Guide/HTML/Using_HTML_sections_and_outlines">使用 HTML 区段和大纲</a>:HTML5 语义元素和大纲算法进阶指南。</li> +</ul> + +<p>{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/Advanced_text_formatting", "Learn/HTML/Introduction_to_HTML/Debugging_HTML", "Learn/HTML/Introduction_to_HTML")}}</p> + +<h2 id="本章目录">本章目录</h2> + +<ul> + <li><a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/Getting_started">开始学习 HTML</a></li> + <li><a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML">“头”里有什么?HTML 元信息</a></li> + <li><a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/HTML_text_fundamentals">HTML 文字处理初步</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks">创建超链接</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Advanced_text_formatting">高级文字格式</a></li> + <li><a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/文件和网站结构">文档和站点结构</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Debugging_HTML">HTML 调试</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Marking_up_a_letter">课程测验:为信件排版</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Structuring_a_page_of_content">课程测验:构建内容丰富的网页</a></li> +</ul> diff --git a/files/zh-cn/learn/html/multimedia_and_embedding/adding_vector_graphics_to_the_web/index.html b/files/zh-cn/learn/html/multimedia_and_embedding/adding_vector_graphics_to_the_web/index.html new file mode 100644 index 0000000000..3b292c1b9c --- /dev/null +++ b/files/zh-cn/learn/html/multimedia_and_embedding/adding_vector_graphics_to_the_web/index.html @@ -0,0 +1,361 @@ +--- +title: 在网页中添加矢量图形 +slug: Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web +tags: + - HTML + - SVG + - 图像 + - 指南 +translation_of: Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies", "Learn/HTML/Multimedia_and_embedding/Responsive_images", "Learn/HTML/Multimedia_and_embedding")}}</div> + +<div class="summary"> +<p>矢量图形在很多情况下非常有用 — 它们拥有较小的文件尺寸,却高度可缩放,所以它们不会在镜头拉近或者放大图像时像素化。在这篇文章中,我们将为您呈现如何在网页中添加矢量图形。</p> +</div> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">前提:</th> + <td>你需要了解 <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML">HTML的基本知识</a> 并且知道如何 <a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Images_in_HTML">在你的文档中插入图片</a>.</td> + </tr> + <tr> + <th scope="row">目标:</th> + <td>了解如何嵌入 SVG (矢量) 图形到网页中。</td> + </tr> + </tbody> +</table> + +<div class="note"> +<p><span style="font-size: 14px;"><strong>提示:</strong></span> 本文的目的并不是教你 SVG;仅仅是告诉你它是什么,以及如何在网页中添加它。</p> +</div> + +<h2 id="什么是矢量图形?">什么是矢量图形?</h2> + +<p>在网上,你会和两种类型的图片打交道 — 位图和矢量图:</p> + +<ul> + <li>位图使用像素网格来定义 — 一个位图文件精确得包含了每个像素的位置和它的色彩信息。流行的位图格式包括 Bitmap (<code>.bmp</code>), PNG (<code>.png</code>), JPEG (<code>.jpg</code>), and GIF (<code>.gif</code>.)</li> + <li>矢量图使用算法来定义 — 一个矢量图文件包含了图形和路径的定义,电脑可以根据这些定义计算出当它们在屏幕上渲染时应该呈现的样子。 {{glossary("SVG")}} 格式可以让我们创造用于 Web 的精彩的矢量图形。</li> +</ul> + +<p>为了让你清楚的认识到两者的区别,我们来一个例子。你可以在我们的 Github 仓库中在线查看这个例子:<a href="http://mdn.github.io/learning-area/html/multimedia-and-embedding/adding-vector-graphics-to-the-web/vector-versus-raster.html">vector-versus-raster.html</a> — 它并排展示了两个看起来一致的图像,一个红色的五角星以及黑色的阴影。不同的是,左边的是 PNG,而右边的是 SVG 图像。</p> + +<p>当你放大网页的时候,区别就会变得明显起来 — 随着你的放大,PNG 图片变得像素化了,因为它存储是每个像素的颜色和位置信息 — 当它被放大时,每个像素就被放大以填满屏幕上更多的像素,所以图像就会开始变得马赛克感觉。矢量图像看起来仍然效果很好且清晰,因为无论它的尺寸如何,都使用算法来计算出图像的形状,仅仅是根据放大的倍数来调整算法中的值。</p> + +<p><img alt="Two star images, one raster and one vector. At their default size they look identical" src="https://mdn.mozillademos.org/files/12866/raster-vector-default-size.png" style="display: block; height: 112px; margin: 0px auto; width: 223px;"></p> + +<p><img alt="Two star images zoomed in. The raster one on the left starts to look pixellated, whereas the vector one still looks crisp." src="https://mdn.mozillademos.org/files/12868/raster-vector-zoomed.png" style="display: block; height: 328px; margin: 0px auto; width: 677px;"></p> + +<div class="note"> +<p><strong>注意</strong>: 上面的图片实际上都是 PNG 图片 —— 每个例子中左边的图片代表光栅图片,右边的星星代表矢量图。还有,访问 <a href="http://mdn.github.io/learning-area/html/multimedia-and-embedding/adding-vector-graphics-to-the-web/vector-versus-raster.html">vector-versus-raster.html</a> 示例来查看真正的例子!</p> +</div> + +<p>此外,矢量图形相较于同样的位图,通常拥有更小的体积,因为它们仅需储存少量的算法,而不是逐个储存每个像素的信息。</p> + +<h2 id="SVG是什么?">SVG是什么?</h2> + +<p><a href="/zh-CN/docs/Web/SVG">SVG</a> 是用于描述矢量图像的{{glossary("XML")}}语言。 它基本上是像HTML一样的标记,只是你有许多不同的元素来定义要显示在图像中的形状,以及要应用于这些形状的效果。 SVG用于标记图形,而不是内容。 非常简单,你有一些元素来创建简单图形,如{{svgelement("circle")}} 和{{svgelement("rect")}}。更高级的SVG功能包括 {{svgelement("feColorMatrix")}}(使用变换矩阵转换颜色){{svgelement("animate")}} (矢量图形的动画部分)和 {{svgelement("mask")}}(在图像顶部应用模板)</p> + +<p>作为一个简单的例子,以下代码创建一个圆和一个矩形:</p> + +<pre class="brush: html notranslate"><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></pre> + +<p>这将创建以下输出:(如果无法查看图片,<a href="https://mdn.mozillademos.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web$samples/What_is_SVG?revision=1467150">这里</a>)<img alt="" src="https://mdn.mozillademos.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web$samples/What_is_SVG?revision=1467150" style="height: 100px; width: 100px;"></p> + +<p>{{ EmbedLiveSample('What_is_SVG', 300, 200, "", "", "hide-codepen-jsfiddle") }}</p> + +<p>从上面的例子可以看出,SVG很容易手工编码。 是的,您可以在文本编辑器中手动编写简单的SVG,但是对于复杂的图像,这很快就开始变得非常困难。 为了创建SVG图像,大多数人使用矢量图形编辑器,如 <a href="https://inkscape.org/en/">Inkscape</a> 或 <a href="https://en.wikipedia.org/wiki/Adobe_Illustrator">Illustrator</a>。 这些软件包允许您使用各种图形工具创建各种插图,并创建照片的近似值(例如Inkscape的跟踪位图功能)。</p> + +<p>SVG除了迄今为止所描述的以外还有其他优点:</p> + +<ul> + <li>矢量图像中的文本仍然可访问(这也有利于 {{glossary("SEO")}}))。</li> + <li>SVG 可以很好地适应样式/脚本,因为图像的每个组件都是可以通过CSS或通过JavaScript编写的样式的元素。</li> +</ul> + +<p>那么为什么会有人想使用光栅图形而不是SVG? 其实 SVG 确实有一些缺点:</p> + +<ul> + <li>SVG非常容易变得复杂,这意味着文件大小会增加; 复杂的SVG也会在浏览器中占用很长的处理时间。</li> + <li>SVG可能比栅格图像更难创建,具体取决于您尝试创建哪种图像。</li> + <li>旧版浏览器不支持SVG,因此如果您需要在网站上支持旧版本的 IE,则可能不适合(SVG从IE9开始得到支持)。</li> +</ul> + +<p>由于上述原因,光栅图形更适合照片那样复杂精密的图像。</p> + +<div class="note"> +<p><strong>注意:</strong>在Inkscape中,将文件保存为纯SVG以节省空间。 另请参阅<a href="http://tavmjong.free.fr/INKSCAPE/MANUAL/html/Web-Inkscape.html">如何为Web准备SVG</a>。</p> +</div> + +<h2 id="将SVG添加到页面">将SVG添加到页面</h2> + +<p>在本节中,我们将介绍将SVG矢量图形添加到网页的不同方式。</p> + +<h3 id="快捷方式:htmlelementimg">快捷方式:{{htmlelement("img")}}</h3> + +<p>要通过 {{htmlelement("img")}}元素嵌入SVG,你只需要按照预期的方式在 src 属性中引用它。你将需要一个<code>height</code>或<code>width</code>属性(或者如果您的SVG没有固有的宽高比)。如果您还没使用过<font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);"><img></span></font>元素,请阅读<a href="/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/Images_in_HTML">HTML中的图片</a>教程 。</p> + +<pre class="brush: html notranslate"><img + src="equilateral.svg" + alt="triangle with all three sides equal" + height="87px" + width="100px" /> +</pre> + +<h4 id="优点">优点</h4> + +<ul> + <li>快速,熟悉的图像语法与<code>alt</code>属性中提供的内置文本等效。</li> + <li>可以通过在{{htmlelement("a")}}元素嵌套<code><img></code>,使图像轻松地成为超链接。</li> +</ul> + +<h4 id="缺点">缺点</h4> + +<ul> + <li>无法使用JavaScript操作图像。</li> + <li>如果要使用CSS控制SVG内容,则必须在SVG代码中包含内联CSS样式。 (从SVG文件调用的外部样式表不起作用)</li> + <li>不能用CSS伪类来重设图像样式(如<code>:focus</code>)。</li> +</ul> + +<h3 id="疑难解答和跨浏览器支持">疑难解答和跨浏览器支持</h3> + +<p>对于不支持SVG(IE 8及更低版本,Android 2.3及更低版本)的浏览器,您可以从<code>src</code>属性引用PNG或JPG,并使用{{htmlattrxref("srcset", "img")}}属性 只有最近的浏览器才能识别)来引用SVG。 在这种情况下,仅支持浏览器将加载SVG - 较旧的浏览器将加载PNG:</p> + +<pre class="brush: html notranslate"><img src="equilateral.png" alt="triangle with equal sides" srcset="equilateral.svg"> +</pre> + +<p>您还可以使用SVG作为CSS背景图像,如下所示。 在下面的代码中,旧版浏览器会坚持他们理解的PNG,而较新的浏览器将加载SVG:</p> + +<pre class="brush: css notranslate"><code>background: url("fallback.png") no-repeat center;</code> +background<code>-image: url("image.svg"); +background-size: contain;</code></pre> + +<p>像上面描述的<code><img></code>方法一样,使用 CSS 背景图像插入SVG 意味着它不能被 JavaScript 操作,并且也受到相同的 CSS 限制。</p> + +<p>如果 SVG 根本没有显示,可能是因为你的服务器设置不正确。 如果是这个问题,<a href="/zh-CN/docs/Web/SVG/Tutorial/Getting_Started#A_Word_on_Webservers">这篇文章</a>将告诉你正确方向。</p> + +<h3 id="如何在HTML中引入SVG代码">如何在HTML中引入SVG代码</h3> + +<p><br> + 你还可以在文本编辑器中打开SVG文件,复制SVG代码,并将其粘贴到HTML文档中 - 这有时称为将<strong>SVG内联</strong>或<strong>内联SVG</strong>。确保您的SVG代码在<code><a href="https://developer.mozilla.org/en-US/docs/Web/SVG/Element/svg"><svg></svg></a></code>标签中(不要在外面添加任何内容)。这是一个非常简单的示例,您可以粘贴到文档中:</p> + +<pre class="brush: html notranslate"><svg width="300" height="200"> + <rect width="100%" height="100%" fill="green" /> +</svg> +</pre> + +<h4 id="优点_2">优点</h4> + +<ul> + <li>将 SVG 内联减少 HTTP 请求,可以减少加载时间。</li> + <li>您可以为 SVG 元素分配<code>class</code>和<code>id</code>,并使用 CSS 修改样式,无论是在SVG中,还是 HTML 文档中的 CSS 样式规则。 实际上,您可以使用任何 <a href="/zh-CN/docs/Web/SVG/Attribute#Presentation_attributes">SVG外观属性</a> 作为CSS属性。</li> + <li>内联SVG是唯一可以让您在SVG图像上使用CSS交互(如<code>:focus</code>)和CSS动画的方法(即使在常规样式表中)。</li> + <li>您可以通过将 SVG 标记包在{{htmlelement("a")}}元素中,使其成为超链接。</li> +</ul> + +<h4 id="缺点_2">缺点</h4> + +<ul> + <li>这种方法只适用于在一个地方使用的SVG。多次使用会导致资源密集型维护(resource-intensive maintenance)。</li> + <li>额外的 SVG 代码会增加HTML文件的大小。</li> + <li>浏览器不能像缓存普通图片一样缓存内联SVG。</li> + <li>您可能会在{{svgelement("foreignObject")}} 元素中包含回退,但支持 SVG 的浏览器仍然会下载任何后备图像。你需要考虑仅仅为支持过时的浏览器,而增加额外开销是否真的值得。</li> +</ul> + +<ul> +</ul> + +<h3 id="如何使用_htmlelementiframe_嵌入SVG">如何使用 {{htmlelement("iframe")}} 嵌入SVG</h3> + +<p>您可以在浏览器中打开 SVG 图像,就像网页一样。 因此,使用<code><iframe></code>嵌入 SVG 文档就像我们在 <a href="/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/其他嵌入技术">从对象到iframe - 其他嵌入技术</a> 中进行研究一样。</p> + +<p>这是一个快速回顾:</p> + +<pre class="brush: html notranslate"><iframe src="triangle.svg" width="500" height="500" sandbox> + <img src="triangle.png" alt="Triangle with three unequal sides" /> +</iframe></pre> + +<p>这绝对不是最好的方法:</p> + +<h4 id="缺点_3">缺点</h4> + +<ul> + <li>如你所知, <code>iframe</code>有一个回退机制,如果浏览器不支持<code>iframe</code>,则只会显示回退。</li> + <li>此外,除非 SVG 和您当前的网页具有相同的 {{glossary('origin')}},否则你不能在主页面上使用 JavaScript 来操纵 SVG。</li> +</ul> + +<h2 id="动手学习:使用SVG">动手学习:使用SVG</h2> + +<p>在这个动手学习部分中,我们希望你能够体验一下 SVG 的乐趣。 在下面的“input”部分,您将看到我们已经提供了一些样例来开始使用。 您还可以访问 <a href="/zh-CN/docs/Web/SVG/Element">SVG元素参考</a>,了解更多关于SVG可以使用的其他玩具的细节,也可以尝试一下。 这部分都是为了锻炼你的研究技巧,并且有一些乐趣。</p> + +<p>如果你卡住了,无法使你的代码工作,你可以随时使用 Reset 按钮进行重置。</p> + +<div class="hidden"> +<h6 id="Playable_code">Playable code</h6> + +<pre class="brush: html notranslate"><code><h2>Live output</h2> + +<div class="output" style="min-height: 50px;"> +</div> + +<h2>Editable code</h2> +<p class="a11y-label">Press Esc to move focus away from the code area (Tab inserts a tab character).</p> + +<textarea id="code" class="input" style="width: 95%;min-height: 200px;"> + <svg width="100%" height="100%"> + <rect width="100%" height="100%" fill="red" /> + <circle cx="100%" cy="100%" r="150" fill="blue" stroke="black" /> + <polygon points="120,0 240,225 0,225" fill="green"/> + <text x="50" y="100" font-family="Verdana" font-size="55" + fill="white" stroke="black" stroke-width="2"> + Hello! + </text> + </svg> +</textarea> + +<div class="playable-buttons"> + <input id="reset" type="button" value="Reset"> + <input id="solution" type="button" value="Show solution" disabled> +</div></code></pre> + +<pre class="brush: css notranslate"><code>html { + font-family: sans-serif; +} + +h2 { + font-size: 16px; +} + +.a11y-label { + margin: 0; + text-align: right; + font-size: 0.7rem; + width: 98%; +} + +body { + margin: 10px; + background: #f5f9fa; +}</code></pre> + +<pre class="brush: js notranslate"><code>var textarea = document.getElementById('code'); +var reset = document.getElementById('reset'); +var solution = document.getElementById('solution'); +var output = document.querySelector('.output'); +var code = textarea.value; +var userEntry = textarea.value; + +function updateCode() { + output.innerHTML = textarea.value; +} + +reset.addEventListener('click', function() { + textarea.value = code; + userEntry = textarea.value; + solutionEntry = htmlSolution; + solution.value = 'Show solution'; + updateCode(); +}); + +solution.addEventListener('click', function() { + if(solution.value === 'Show solution') { + textarea.value = solutionEntry; + solution.value = 'Hide solution'; + } else { + textarea.value = userEntry; + solution.value = 'Show solution'; + } + updateCode(); +}); + +var htmlSolution = ''; +var solutionEntry = htmlSolution; + +textarea.addEventListener('input', updateCode); +window.addEventListener('load', updateCode); + +// stop tab key tabbing out of textarea and +// make it write a tab at the caret position instead + +textarea.onkeydown = function(e){ + if (e.keyCode === 9) { + e.preventDefault(); + insertAtCaret('\t'); + } + + if (e.keyCode === 27) { + textarea.blur(); + } +}; + +function insertAtCaret(text) { + var scrollPos = textarea.scrollTop; + var caretPos = textarea.selectionStart; + + var front = (textarea.value).substring(0, caretPos); + var back = (textarea.value).substring(textarea.selectionEnd, textarea.value.length); + textarea.value = front + text + back; + caretPos = caretPos + text.length; + textarea.selectionStart = caretPos; + textarea.selectionEnd = caretPos; + textarea.focus(); + textarea.scrollTop = scrollPos; +} + +// Update the saved userCode every time the user updates the text area code + +textarea.onkeyup = function(){ + // We only want to save the state when the user code is being shown, + // not the solution, so that solution is not saved over the user code + if(solution.value === 'Show solution') { + userEntry = textarea.value; + } else { + solutionEntry = textarea.value; + } + + updateCode(); +};</code></pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code', 700, 500, "", "", "hide-codepen-jsfiddle") }}</p> + +<h2 id="总结">总结</h2> + +<p>本文提供了一个矢量图形和 SVG 的快速浏览,让你了解他们的作用,以及如何在网页中引入 SVG。 它从来没有打算成为学习 SVG 的完整教程,只是一个指南,让你在网上遇到 SVG 时知道它是什么。 所以不要觉得你不是一个 SVG 专家而担心。如果你想了解更多关于它的工作原理,我们在下面列出了一些可能会帮助您的信息。</p> + +<p>在本模块的最后一篇文章中,我们将详细探索响应式图像,查看 HTML 可以让您的图像在不同设备上更好地适配。</p> + +<h2 id="相关链接">相关链接</h2> + +<ul> + <li><a href="https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Getting_Started">SVG tutorial</a> on MDN</li> + <li><a href="http://thenewcode.com/744/Making-SVG-Responsive">Quick tips for responsive SVGs</a></li> + <li><a href="http://tympanus.net/codrops/2014/08/19/making-svgs-responsive-with-css/">Sara Soueidan's tutorial on responsive SVG images</a></li> + <li><a href="http://www.w3.org/TR/SVG-access/">Accessibility benefits of SVG</a></li> + <li><a href="https://css-tricks.com/scale-svg/">How to scale SVGs </a> (它不像光栅图形那么简单!)</li> +</ul> + +<p>{{PreviousMenuNext("Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies", "Learn/HTML/Multimedia_and_embedding/Responsive_images", "Learn/HTML/Multimedia_and_embedding")}}</p> + + + +<h2 id="在这个模块中">在这个模块中</h2> + +<ul> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Images_in_HTML">Images in HTML</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Video_and_audio_content">Video and audio content</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies">From <object> to <iframe> — other embedding technologies</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web">Adding vector graphics to the Web</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images">Responsive images</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Mozilla_splash_page">Mozilla splash page</a></li> +</ul> diff --git a/files/zh-cn/learn/html/multimedia_and_embedding/images_in_html/index.html b/files/zh-cn/learn/html/multimedia_and_embedding/images_in_html/index.html new file mode 100644 index 0000000000..78b73be90b --- /dev/null +++ b/files/zh-cn/learn/html/multimedia_and_embedding/images_in_html/index.html @@ -0,0 +1,476 @@ +--- +title: HTML中的图片 +slug: Learn/HTML/Multimedia_and_embedding/Images_in_HTML +translation_of: Learn/HTML/Multimedia_and_embedding/Images_in_HTML +--- +<div>{{LearnSidebar}}</div> + +<div>{{NextMenu("Learn/HTML/Multimedia_and_embedding/Video_and_audio_content", "Learn/HTML/Multimedia_and_embedding")}}</div> + +<p class="summary">在一开始时,Web仅有文本,那真的是很无趣。幸运的是,没过多久网页上就能嵌入图片和其他有趣的内容了。虽然还有许多其他类型的多媒体,但是从地位比较低的{{htmlelement("img")}}元素开始是符合逻辑的,它常常被用来在网页中嵌入一张简单的图片。在这篇文章中,我们将看到怎样深入的使用它,包括基本的用{{htmlelement("figure")}}来添加说明文字,以及怎样把它和CSS背景图片链接起来。</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">预备知识:</th> + <td>掌握基本的电脑知识,<a href="/zh-CN/docs/Learn/Getting_started_with_the_web/Installing_basic_software">安装基本软件</a>,基本的<a href="/zh-CN/docs/Learn/Getting_started_with_the_web/Dealing_with_files">文件处理</a>知识,熟悉<a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Getting_started">HTML基础</a></td> + </tr> + <tr> + <th scope="row">学习目标:</th> + <td>学习如何在 HTML 页面插入简单的图片,为图片添加简单的说明,以及 CSS 背景图片与 HTML 图片的关系。</td> + </tr> + </tbody> +</table> + +<h2 id="怎样将一幅图片放到网页上">怎样将一幅图片放到网页上?</h2> + +<p>我们可以用{{htmlelement("img")}} 元素来把图片放到网页上。它是一个空元素(它不需要包含文本内容或闭合标签),最少只需要一个 <code>src</code> (一般读作其全称 <em>source)</em>来使其生效。<code>src</code> 属性包含了指向我们想要引入的图片的路径,可以是相对路径或绝对URL,就像 {{htmlelement("a")}} 元素的 <code>href</code> 属性一样。</p> + +<div class="note"> +<p><strong>注意:</strong>在继续之前,你应该阅读<a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks#URLs与路径(path)快速入门">快速入门URL和路径</a>来复习一下相对和绝对URL。</p> +</div> + +<p>举个例子来看,如果你有一幅文件名为 <code>dinosaur.jpg</code> 的图片,且它与你的 HTML 页面存放在相同路径下,那么你可以这样嵌入它:</p> + +<pre class="brush: html"><img src="dinosaur.jpg"></pre> + +<p>如果这张图片存储在和 HTML 页面同路径的 <code>images</code> 文件夹下(这也是Google推荐的做法,利于{{glossary("SEO")}}/索引),那么你可以采用如下形式:</p> + +<pre class="brush: html"><img src="images/dinosaur.jpg"></pre> + +<p>以此类推。</p> + +<div class="note"> +<p><strong>注意:</strong>搜索引擎也读取图像的文件名并把它们计入SEO。因此你应该给你的图片取一个描述性的文件名:<code>dinosaur.jpg</code> 比 <code>img835.png </code>要好。</p> +</div> + +<p>你也可以像下面这样使用绝对路径:</p> + +<pre class="brush: html"><img src="https://www.example.com/images/dinosaur.jpg"></pre> + +<p>但是这种方式是不被推荐的,这样做只会使浏览器做更多的工作,例如重新通过 DNS 再去寻找 IP 地址。通常我们都会把图片和 HTML 放在同一个服务器上。</p> + +<div class="warning"> +<p><strong>警告:</strong>大多数图片是有版权的。<strong>不要</strong>在你的网页上使用一张图片,除非:</p> + +<ol> + <li>你是图片版权所有者</li> + <li>你有图片版权所有者明确的、书面上的使用授权</li> + <li>你有充分的证据证明这张图片是公共领域内的</li> +</ol> + +<p>侵犯版权是违法并且不道德的。此外,在得到授权之前<strong>永远不要</strong>把你的<code>src</code>属性指向其他人网站上的图片。这被称为"盗链(hotlinking)"。同样,盗取其他人的带宽也是违法的。而且这会降低你的页面的加载速度,而且图片可能会在不受你控制的情况下被移走或用别的令人尴尬的东西替换掉。</p> +</div> + +<p>我们上面的代码会展示如下的结果页面:</p> + +<p><img alt="A basic image of a dinosaur, embedded in a browser, with Images in HTML written above it" src="https://mdn.mozillademos.org/files/12700/basic-image.png" style="display: block; height: 700px; margin: 0px auto; width: 700px;"></p> + +<div class="note"> +<p><strong>注意:</strong>像{{htmlelement("img")}}和{{htmlelement("video")}}这样的元素有时被称之为<strong>替换元素</strong>,因为这样的元素的内容和尺寸由外部资源(像是一个图片或视频文件)所定义,而不是元素自身。</p> +</div> + +<div class="note"> +<p><strong>注意:</strong>你可以在<a href="https://mdn.github.io/learning-area/html/multimedia-and-embedding/images-in-html/index.html">GitHub上的这个网页</a>看到这个例子的运行结果(也可以看到<a href="https://github.com/mdn/learning-area/blob/master/html/multimedia-and-embedding/images-in-html/index.html">源码</a>)。</p> +</div> + +<h3 id="备选文本">备选文本</h3> + +<p>下一个我们讨论的属性是 <code>alt</code> ,它的值应该是对图片的文字描述,用于在图片无法显示或不能被看到的情况。例如,上面的例子可以做如下改进:</p> + +<pre class="brush: html"><img src="images/dinosaur.jpg" + alt="The head and torso of a dinosaur skeleton; + it has a large head with long sharp teeth"></pre> + +<p>测试<code>alt</code> 属性最简单的方式就是故意拼错图片文件名,这样浏览器就无法找到该图片从而显示备选的文本。如果我们将上例的图片文件名改为 <code>dinosooooor.jpg</code>,浏览器就不能显示图片,而显示:</p> + +<p><img alt="The Images in HTML title, but this time the dinosaur image is not displayed, and alt text is in its place." src="https://mdn.mozillademos.org/files/12702/alt-text.png" style="display: block; height: 700px; margin: 0px auto; width: 700px;"></p> + +<p>那么,为什么我们需要备选文本呢?它可以派上用场的原因有很多:</p> + +<ul> + <li>用户有视力障碍,通过<a href="https://zh.wikipedia.org/wiki/%E8%9E%A2%E5%B9%95%E9%96%B1%E8%AE%80%E5%99%A8">屏幕阅读器</a>来浏览网页 。事实上,给图片一个备选的描述文本对大多数用户都是很有用的。</li> + <li>就像上面所说的,你也许会把图片的路径或文件名拼错。</li> + <li>浏览器不支持该图片类型。某些用户仍在使用纯文本的浏览器,例如 <a href="https://en.wikipedia.org/wiki/Lynx_%28web_browser%29">Lynx</a>,这些浏览器会把图片替换为描述文本。</li> + <li>你会想提供一些文字描述来给搜索引擎使用,例如搜索引擎可能会将图片的文字描述和查询条件进行匹配。</li> + <li>用户关闭的图片显示以减少数据的传输,这在手机上是十分普遍的,并且在一些国家带宽有限且昂贵。</li> +</ul> + +<p>你到底应该在 <code>alt</code> 里写点什么呢?这首先取决于为什么这张图片会在这儿,换句话说,如果这张图片没显示出来,会少了什么:</p> + +<ul> + <li><strong>装饰:</strong>如果图片只是用于装饰,而不是内容的一部分,可以写一个空的<code>alt=""</code> 。例如,屏幕阅读器不会浪费时间对用户读出不是核心需要的内容。实际上装饰性图片就不应该放在HTML文件里, {{anch("CSS background images")}}才应该用于插入装饰图片,但如果这种情况无法避免, <code>alt=""</code>会是最佳处理方案。</li> + <li><strong>内容:</strong>如果你的图片提供了重要的信息,就要在<code>alt</code>文本中简要的提供相同的信息,甚至更近一步,把这些信息写在主要的文本内容里,这样所有人都能看见。不要写冗余的备选文本(如果在主要文本中将所有的段落都重复两遍,对于没有失明的用户来说多烦啊!),如果在主要文本中已经对图片进行了充分的描述,写<code>alt=""</code>就好。</li> + <li><strong>链接:</strong>如果你把图片嵌套在{{htmlelement("a")}}标签里,来把图片变成链接,那你还必须<a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks#用清晰的链接措辞。">提供无障碍的链接文本</a>。在这种情况下,你可以写在同一个<font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);"><a></span></font>元素里,或者写在图片的<code>alt</code>属性里,随你喜欢。</li> + <li><strong>文本:</strong>你不应该将文本放到图像里。例如,如果你的主标题需要有阴影,你可以<a href="/zh-CN/docs/Web/CSS/text-shadow">用CSS</a>来达到这个目的,而不是把文本放到图片里。如果真的必须这么做,那就把文本也放到<code>alt</code>里。</li> +</ul> + +<p>本质上,关键在于在图片无法被看见时也提供一个可用的体验,这确保了所有人都不会错失一部分内容。尝试在浏览器中使图片不可见然后看看网页变成什么样了,你会很快意识到在图片无法显示时备选文本能帮上多大忙。</p> + +<div class="note"> +<p><strong>注意:</strong>想知道更多,可以看我们的<a href="https://developer.mozilla.org/zh-CN/docs/learn/Accessibility/HTML:%E4%B8%BA%E5%8F%AF%E8%AE%BF%E9%97%AE%E6%80%A7%E6%8F%90%E4%BE%9B%E4%B8%80%E4%B8%AA%E8%89%AF%E5%A5%BD%E7%9A%84%E5%9F%BA%E7%A1%80#%E6%96%87%E6%9C%AC%E6%9B%BF%E4%BB%A3%E5%93%81">备选文本</a>指南</p> +</div> + +<h3 id="宽度和高度">宽度和高度</h3> + +<p>你可以用宽度和高度属性来指定你的图片的高度和宽度(你可以用多种方式找到你的图片的宽度和高度,例如在Mac上,你可以用 <kbd>Cmd</kbd> + <kbd>I</kbd> 来得到显示的图片文件的信息)回到我们的例子,你可以这样做:</p> + +<pre class="brush: html"><img src="images/dinosaur.jpg" + alt="一只恐龙头部和躯干的骨架,它有一个巨大的头,长着锋利的牙齿。" + width="400" + height="341"></pre> + +<p>在正常的情况下,这不会对显示产生很大的影响, 但是如果图片没有显示(例如用户刚刚开始浏览网页,但是图片还没有加载完成),你会注意到浏览器会为要显示的图片留下一定的空间:</p> + +<p><img alt="The Images in HTML title, with dinosaur alt text, displayed inside a large box that results from width and height settings" src="https://mdn.mozillademos.org/files/12706/alt-text-with-width-height.png" style="display: block; height: 700px; margin: 0px auto; width: 700px;"></p> + +<p>这是一件好事情——这使得页面加载的更快速更流畅。</p> + +<p>然而,你不应该使用HTML属性来改变图片的大小。如果你把尺寸设定的太大,最终图片看起来会模糊;如果太小,会在下载远远大于你需要的图片时浪费带宽。如果你没有保持正确的<a href="https://zh.wikipedia.org/wiki/%E9%95%B7%E5%AF%AC%E6%AF%94_(%E5%BD%B1%E5%83%8F)">宽高比</a>,图片可能看起来会扭曲。在把图片放到你的网站页面之前,你应该使用图形编辑器使图片的尺寸正确。</p> + +<div class="note"> +<p><strong>注意:</strong>如果你需要改变图片的尺寸,你应该使用<a href="/zh-CN/docs/Learn/CSS">CSS</a>而不是HTML。</p> +</div> + +<h3 id="Image_titles_图片标题">Image titles 图片标题</h3> + +<p>类似于<a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks#使用<title>添加支持信息">超链接</a>,你可以给图片增加<code>title</code>属性来提供需要更进一步的支持信息。在我们的例子中,可以这样做:</p> + +<pre class="brush: html"><img src="images/dinosaur.jpg" + alt="一只恐龙头部和躯干的骨架,它有一个巨大的头,长着锋利的牙齿。" + width="400" + height="341" + title="A T-Rex on display in the Manchester University Museum"></pre> + +<p>这会给我们一个鼠标悬停提示,看起来就像链接标题:</p> + +<p><img alt="The dinosaur image, with a tooltip title on top of it that reads A T-Rex on display at the Manchester University Museum " src="https://mdn.mozillademos.org/files/12708/image-with-title.png" style="display: block; height: 341px; margin: 0px auto; width: 400px;"></p> + +<p>图片标题并不必须要包含有意义的信息,通常来说,将这样的支持信息放到主要文本中而不是附着于图片会更好。不过,在有些环境中这样做更有用,比如当没有空间显示提示时,也就是在图片栏中。</p> + +<p>然而,这并不是推荐的——title有很多易访问性问题,主要是基于这样一个事实,即屏幕阅读器的支持是不可预测的,大多数浏览器都不会显示它,除非您在鼠标悬停时(例如:title无法访问键盘用户),如果你对更多的信息感兴趣,阅读<a href="https://www.24a11y.com/2017/the-trials-and-tribulations-of-the-title-attribute/" rel="noopener">The Trials and Tribulations of the Title Attribute</a> by Scott O'Hara.</p> + +<h3 id="动手练习:嵌入一张图片">动手练习:嵌入一张图片</h3> + +<p>好,轮到你了!在这个动手练习中, 我们希望你可以做一个简单的嵌入图片练习。 你有一个基本的 {{htmlelement("img")}} 标签; 我们希望你可以把下面这个 URL 所指向的图片嵌入到 HTML 中:</p> + +<p>https://raw.githubusercontent.com/mdn/learning-area/master/html/multimedia-and-embedding/images-in-html/dinosaur_small.jpg</p> + +<p>之前我们说过永远不要从其他服务器热链接图片,但这次只是出于学习目的,所以我们会允许你这么做一次。</p> + +<p>我们还希望你可以:</p> + +<ul> + <li>添加 <code>alt</code>文字,添加完成后,可以故意把 URL 写错,来检查 {{htmlelement("alt")}} 的效果。</li> + <li>设置图片正确的 <code>width</code> 和 <code>height</code> 属性(提示:宽 200px,高 171px),然后再将宽和高的值进行改变,看看会有什么影响.</li> + <li>在图片上设置 <code>title</code> 属性。</li> +</ul> + +<p>如果你遇到了错误,你可以按 reset 按钮来重置。如果你遇到了困难无法完成, 按下 Show solution 按钮来看一下答案。</p> + +<div class="hidden"> +<h6 id="Playable_code">Playable code</h6> + +<pre class="brush: html"><!DOCTYPE html> +<html lang="zh-CN"> + <head> + <meta charset="utf-8"> + <style> + body { font-family: '微软雅黑', Helvetica, Arial, sans-serif; margin: 10px; background: #f5f9fa; } + h2 { font-size: 16px; } + code, textarea { font-family: Consolas, Menlo, monospace; } + .output { min-height: 200px; } + .input { min-height: 100px; width: 95%; } + .a11y-label { margin: 0; text-align: right; font-size: 0.7rem; width: 98%; } + .controls { width: 96%; text-align: right; } + </style> + + </head> + <body> + <h2>实时输出</h2> + <div class="output"></div> + + <h2>可编辑代码</h2> + <p class="a11y-label">按 ESC 退出编辑区域,按 Tab 可插入制表符 <code>'\t'</code> </p> + <textarea id="code" class="input"></textarea> + + <div class="controls"> + <button id="btn-reset">重置</button> + <button id="btn-solution">显示答案</button> + </div> + <script> + const btnReset = document.getElementById('btn-reset'); + const btnSolution = document.getElementById('btn-solution'); + const blockOutput = document.querySelector('.output'); + const blockInput = document.querySelector('.input'); + const original = 'https://raw.githubusercontent.com/mdn/learning-area/master/html/multimedia-and-embedding/images-in-html/dinosaur_small.jpg'; + const answer = +`<img src="https://raw.githubusercontent.com/mdn/learning-area/master/html/multimedia-and-embedding/images-in-html/dinosaur_small.jpg" + alt="一只恐龙头部和躯干的骨架,它有一个巨大的头,长着锋利的牙齿。" + width="200" + height="171" + title="曼彻斯特大学博物馆展出的一只霸王龙的化石">`; + let userEntry = ""; + + init(); + btnReset.addEventListener('click', init); + + btnSolution.addEventListener('click', () => { + if (btnSolution.textContent === '显示答案') { + blockInput.value = + blockOutput.innerHTML = answer; + btnSolution.textContent = '隐藏答案'; + } else { + blockInput.value = + blockOutput.innerHTML = userEntry; + btnSolution.textContent = '显示答案'; + } + }); + + blockInput.addEventListener('keydown', (e) => { + switch (e.key) { + case 'Tab': + e.preventDefault(); + insertAtCursor('\t'); + break; + case "Escape": + blockInput.blur(); + break; + } + }); + + blockInput.addEventListener('keyup', () => { + userEntry = blockInput.value; + blockOutput.innerHTML = blockInput.value; + if (btnSolution.textContent === '隐藏答案') { + btnSolution.textContent = '显示答案'; + } + }); + + function init() { + userEntry = + blockOutput.innerHTML = + blockInput.value = original; + btnSolution.textContent = '显示答案'; + } + + function insertAtCursor(text) { + const scrollPos = blockInput.scrollTop; + const cursorPos = blockInput.selectionStart; + + const front = blockInput.value.substring(0, cursorPos); + const back = blockInput.value.substring( + blockInput.selectionEnd, blockInput.value.length); + + blockInput.value = front + text + back; + blockInput.selectionStart = + blockInput.selectionEnd = cursorPos + text.length; + blockInput.focus(); + blockInput.scrollTop = scrollPos; + } + </script> + </body> +</html></pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code', 700, 500) }}</p> + +<h2 id="通过为图片搭配说明文字的方式来解说图片">通过为图片搭配说明文字的方式来解说图片</h2> + +<p>说到说明文字, 这里有很多种方法让你添加一段说明文字来搭配图片。比如,没有人会阻止你这么做:</p> + +<pre class="brush: html"><div class="figure"> + <img src="/images/dinosaur_small.jpg" + alt="一只恐龙头部和躯干的骨架,它有一个巨大的头,长着锋利的牙齿。" + width="400" + height="341"> + <p>曼彻斯特大学博物馆展出的一只霸王龙的化石</p> +</div> +</pre> + +<p>这是可以的 , {{htmlelement("p")}} 中包含了你需要的内容,以及方便使用 CSS 的一种很好的风格。但是这里有一个问题 ,从语义的角度上来讲,{{htmlelement("img")}} 和 {{htmlelement("p")}} 并没有什么联系,这会给使用屏幕阅读的人造成问题,比如当你有 50 张图片和其搭配的 50 段说明文字,那么一段说明文字是和哪张图片有关联的呢?</p> + +<p>有一个更好的做法是使用 HTML5 的 {{htmlelement("figure")}} 和 {{htmlelement("figcaption")}} 元素,它正是为此而被创造出来的:为图片提供一个语义容器,在标题和图片之间建立清晰的关联。我们之前的例子可以重写为:</p> + +<pre><figure> + <img src="https://raw.githubusercontent.com/mdn/learning-area/master/html/multimedia-and-embedding/images-in-html/dinosaur_small.jpg" + alt="一只恐龙头部和躯干的骨架,它有一个巨大的头,长着锋利的牙齿。" + width="400" + height="341"> + <figcaption>曼彻斯特大学博物馆展出的一只霸王龙的化石</figcaption> +</figure> +</pre> + +<p>这个 {{htmlelement("figcaption")}} 元素 告诉浏览器和其他辅助的技术工具这段说明文字描述了 {{htmlelement("figure")}} 元素的内容.</p> + +<div class="note"> +<p><strong>注意:</strong>从无障碍的角度来说,说明文字和 {{htmlattrxref('alt','img')}} 文本扮演着不同的角色。看得见图片的人们同样可以受益于说明文字,而 {{htmlattrxref('alt','img')}} 文字只有在图片无法显示时才这样。 所以,说明文字和 <code>alt</code> 的内容不应该一样,因为当图片无法显示时,它们会同时出现。尝试让你的图片不显示,看看效果如何。</p> +</div> + +<p>注意 {{htmlelement("figure")}} 里不一定要是一张图片,只要是一个这样的独立内容单元:</p> + +<ul> + <li>用简洁、易懂的方式表达意图。</li> + <li>可以置于页面线性流的某处。</li> + <li>为主要内容提供重要的补充说明。</li> +</ul> + +<p>{{htmlelement("figure")}} 可以是几张图片、一段代码、音视频、方程、表格或别的。</p> + +<h3 id="动手练习_创建一个_figure">动手练习: 创建一个 figure</h3> + +<p>在这个动手练习的部分中, 我们希望你把本章节中的上一个动手练习完成的代码拿过来,把它转换为一个 figure:</p> + +<ul> + <li>把之前的代码放入 {{htmlelement("figure")}} 元素中.</li> + <li>将 <code>title</code> 属性的文本复制出来, 删除 <code>title</code> 元素, 然后把文字放入 {{htmlelement("figcaption")}} 元素中,当然这个元素在 {{htmlelement("img")}} 的下面.</li> +</ul> + +<p>如果你遇到了错误,你可以按 reset 按钮来重置. 如果你遇到了困难无法完成, 按下 Show solution 按钮来看一下答案.</p> + +<div class="hidden"> +<h6 id="Playable_code_2">Playable code 2</h6> + +<pre class="brush: html"><!DOCTYPE html> +<html lang="zh-CN"> + <head> + <meta charset="utf-8"> + <style> + body { font-family: '微软雅黑', Helvetica, Arial, sans-serif; margin: 10px; background: #f5f9fa; } + h2 { font-size: 16px; } + code, textarea { font-family: Consolas, Menlo, monospace; } + .output { min-height: 200px; } + .input { min-height: 100px; width: 95%; } + .a11y-label { margin: 0; text-align: right; font-size: 0.7rem; width: 98%; } + .controls { width: 96%; text-align: right; } + </style> + + </head> + <body> + <h2>实时输出</h2> + <div class="output"></div> + + <h2>可编辑代码</h2> + <p class="a11y-label">按 ESC 退出编辑区域,按 Tab 可插入制表符 <code>'\t'</code> </p> + <textarea id="code" class="input"></textarea> + + <div class="controls"> + <button id="btn-reset">重置</button> + <button id="btn-solution">显示答案</button> + </div> + <script> + const btnReset = document.getElementById('btn-reset'); + const btnSolution = document.getElementById('btn-solution'); + const blockOutput = document.querySelector('.output'); + const blockInput = document.querySelector('.input'); + const original = +`<img src="https://raw.githubusercontent.com/mdn/learning-area/master/html/multimedia-and-embedding/images-in-html/dinosaur_small.jpg" + alt="一只恐龙头部和躯干的骨架,它有一个巨大的头,长着锋利的牙齿。" + width="200" + height="171">`; + const answer = +`<figure> + <img src="https://raw.githubusercontent.com/mdn/learning-area/master/html/multimedia-and-embedding/images-in-html/dinosaur_small.jpg" + alt="一只恐龙头部和躯干的骨架,它有一个巨大的头,长着锋利的牙齿。" + width="200" + height="171"> + <figcaption>曼彻斯特大学博物馆展出的一只霸王龙的化石</figcaption> +</figure>`; + let userEntry = ""; + + init(); + btnReset.addEventListener('click', init); + + btnSolution.addEventListener('click', () => { + if (btnSolution.textContent === '显示答案') { + blockInput.value = + blockOutput.innerHTML = answer; + btnSolution.textContent = '隐藏答案'; + } else { + blockInput.value = + blockOutput.innerHTML = userEntry; + btnSolution.textContent = '显示答案'; + } + }); + + blockInput.addEventListener('keydown', (e) => { + switch (e.key) { + case 'Tab': + e.preventDefault(); + insertAtCursor('\t'); + break; + case "Escape": + blockInput.blur(); + break; + } + }); + + blockInput.addEventListener('keyup', () => { + userEntry = blockInput.value; + blockOutput.innerHTML = blockInput.value; + if (btnSolution.textContent === '隐藏答案') { + btnSolution.textContent = '显示答案'; + } + }); + + function init() { + userEntry = + blockOutput.innerHTML = + blockInput.value = original; + btnSolution.textContent = '显示答案'; + } + + function insertAtCursor(text) { + const scrollPos = blockInput.scrollTop; + const cursorPos = blockInput.selectionStart; + + const front = blockInput.value.substring(0, cursorPos); + const back = blockInput.value.substring( + blockInput.selectionEnd, blockInput.value.length); + + blockInput.value = front + text + back; + blockInput.selectionStart = + blockInput.selectionEnd = cursorPos + text.length; + blockInput.focus(); + blockInput.scrollTop = scrollPos; + } + </script> + </body> +</html> +</pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code_2', 700, 500) }}</p> + +<h2 id="CSS_背景图片">CSS 背景图片</h2> + +<p>你也可以使用 CSS 把图片嵌入网站中(JavaScript也行,不过那是另外一个故事了),这个 CSS 属性 {{cssxref("background-image")}} 和另其他 <code>background-*</code> 属性是用来放置背景图片的。比如,为页面中的所有段落设置一个背景图片,你可以这样做:</p> + +<pre class="brush: css">p { + background-image: url("images/dinosaur.jpg"); +}</pre> + +<p>按理说,这种做法相对于 HTML 中插入图片的做法,可以更好地控制图片和设置图片的位置,那么为什么我们还要使用 HTML 图片呢?如上所述,CSS 背景图片只是为了装饰 — 如果你只是想要在你的页面上添加一些漂亮的东西,来提升视觉效果,那 CSS 的做法是可以的。但是这样插入的图片完全没有语义上的意义,它们不能有任何备选文本,也不能被屏幕阅读器识别。这就是 HTML 图片有用的地方了。</p> + +<p>总而言之,如果图像对您的内容里有意义,则应使用HTML图像。 如果图像纯粹是装饰,则应使用CSS背景图片。</p> + +<div class="note"> +<p><strong>提示:</strong>你可以在 <a href="/zh-CN/docs/Learn/CSS">CSS</a> 模块里学到更多关于<a href="/zh-CN/docs/Learn/CSS/Styling_boxes/背景">CSS背景图片</a>的东西。</p> +</div> + +<h2 id="总结">总结</h2> + +<p>目前到此为止,我们详细介绍了图片和说明文字,在下篇文章中,我们将进一步看看如何使用 HTML 在网页上嵌入音频和视频。</p> + +<p>{{NextMenu("Learn/HTML/Multimedia_and_embedding/Video_and_audio_content", "Learn/HTML/Multimedia_and_embedding")}}</p> + +<h2 id="本章目录">本章目录</h2> + +<ul> + <li><a href="/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/Images_in_HTML">HTML 中的图片</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/Video_and_audio_content">视频和音频内容</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies">从 <object> 到 <iframe>:其它嵌入技术</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web">为网页添加向量图形</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images">响应式图片</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/Mozilla_splash_page">Mozilla 宣传页面</a></li> +</ul> diff --git a/files/zh-cn/learn/html/multimedia_and_embedding/index.html b/files/zh-cn/learn/html/multimedia_and_embedding/index.html new file mode 100644 index 0000000000..03297c82fc --- /dev/null +++ b/files/zh-cn/learn/html/multimedia_and_embedding/index.html @@ -0,0 +1,60 @@ +--- +title: 多媒体与嵌入 +slug: Learn/HTML/Multimedia_and_embedding +tags: + - 图像 + - 多媒体 +translation_of: Learn/HTML/Multimedia_and_embedding +--- +<p>{{LearnSidebar}}</p> + +<p class="summary">在这份教程中,到目前为止我们已经看到了许多的文字了。真的很多文字。但是网页除了文本之外什么都没有,真的非常无聊,所以,让我们开始看看怎样让网页动起来。用更多有趣的内容!本模块要探索怎样用HTML来让你的网页包含多媒体,包括可以包含图像的不同方式,以及怎样嵌入视频,甚至是整个其他的网页。</p> + +<h2 id="预备知识">预备知识</h2> + +<p>在你开始本模块之前,你应该已经拥有了关于HTML基础的合理知识,就是之前在<a href="https://developer.mozilla.org/zh-CN/docs/learn/HTML/Introduction_to_HTML">HTML介绍</a>中所述。如果你还没有看过那个模块(或者类似的),先去看看,然后再回来吧!</p> + +<div class="note"> +<p><span style="font-size: 14px;"><strong>提示</strong></span>: 如果你在电脑/平板电脑/其他设备上不能创建你自己的代码文件,你可以尝试在在线代码编辑网站例如<a href="https://jsbin.com/">JSBin</a>或者<a href="https://thimble.mozilla.org/">Thimble</a>来运行(大部分的)代码示例。</p> +</div> + +<h2 id="指南">指南</h2> + +<p>本模块包含以下的文章,它们将会让你了解所有在网页上关于嵌入多媒体的基础方面。</p> + +<dl> + <dt><a href="https://developer.mozilla.org/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/Images_in_HTML">HTML中的图片</a></dt> + <dd>还有其他类型的多媒体要考虑,但是从低调的 {{htmlelement("img")}} 元素开始是符合逻辑的,它常常被用来在网页中嵌入一个简单的图片。在这篇文章中,我们要看看怎样更深入的使用它,包括基础,用标题注解 {{htmlelement("figure")}},以及怎样把它关联到CSS背景图片。</dd> + <dt><a href="https://developer.mozilla.org/zh_CN/docs/Learn/HTML/Multimedia_and_embedding/Video_and_audio_content">视频和音频内容</a></dt> + <dd>接下来,我们将看看怎样在我们的页面上用HTML5的 {{htmlelement("video")}} 和{{htmlelement("audio")}}元素来嵌入视频和音频;包括基础,提供向不同的浏览器提供不同文件格式的访问方式,增加标题和副标题,以及增加对过时的浏览器的兼容。</dd> + <dt><a href="/zh_CN/docs/Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies">从 <object> 到 <iframe> — 其他嵌入技术</a></dt> + <dd>在这一节,我们将来了解一些另辟蹊径的内容,看一组元素,它们可以让你在页面中嵌入许多不同类型的内容: {{htmlelement("iframe")}}, {{htmlelement("embed")}} 和 {{htmlelement("object")}} 元素。 <code><iframe> 用来嵌入其他网页,而另外两者可以帮助你嵌入</code> PDF, SVG, 甚至是 Flash — 一种逐渐退出历史舞台的技术,不过也许你还是能时不时的看到它。</dd> + <dt><a href="/zh_CN/docs/Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web">在页面中添加矢量图像</a></dt> + <dd>矢量图像在一些特定场景中非常有用。不同于常见的格式,比如PNG/JPG, 它们不会在放大的时候变得扭曲或者显示出像素格——它们可以在缩放时保持光滑。本文将为你介绍什么是矢量图像,以及如何在网页中添加流行的 {{glossary("SVG")}} 格式图像。</dd> + <dt><a href="https://developer.mozilla.org/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images">响应式图片</a></dt> + <dd>现在有许多不同的设备类型能够浏览网络 - 从手机到台式电脑 - 在现代网络世界中掌握的一个基本概念就是响应式设计。这是指创建可以自动更改其功能以适应不同屏幕尺寸,分辨率等的网页。稍后将在CSS模块中详细介绍这一点,但是现在我们将看看HTML可用于创建响应式图像的工具,包括{{htmlelement("picture")}}元素。</dd> +</dl> + +<h2 id="评估">评估</h2> + +<p>以下评估将测试您对上述指南中涵盖的HTML基础知识的理解:</p> + +<dl> + <dt><a href="/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/Mozilla_splash_page">Mozilla启动页面</a></dt> + <dd>在这个评估中,我们将测试您对本模块文章中讨论的一些技巧的了解,让您将一些图像和视频添加到一个关于Mozilla的时髦的页面!</dd> +</dl> + +<h2 id="参见">参见</h2> + +<dl> + <dt><a href="/zh-CN/docs/Learn/HTML/Howto/Add_a_hit_map_on_top_of_an_image">在图像的顶部添加一个点阵图</a></dt> + <dd>图像映射提供了一种机制,使图像的不同部分链接到不同的地方(想想地图,链接到有关您点击的每个不同国家的更多信息。)这种技术有时可能是有用的。</dd> + <dt><a href="https://teach.mozilla.org/activities/web-lit-basics-two/">网络素质基础2</a></dt> + <dd> + <p>一个优秀的Mozilla基础课程,探讨并测试了多媒体和嵌入模块中谈到的一些技巧。 深入了解撰写网页的基础知识,设计可访问性,共享资源,使用在线媒体和开放工作。</p> + </dd> +</dl> + +<div id="gtx-trans" style="position: absolute; left: 215px; top: 1116px;"> +<div class="gtx-trans-icon"></div> +</div> diff --git a/files/zh-cn/learn/html/multimedia_and_embedding/mozilla_splash_page/index.html b/files/zh-cn/learn/html/multimedia_and_embedding/mozilla_splash_page/index.html new file mode 100644 index 0000000000..67df99dae4 --- /dev/null +++ b/files/zh-cn/learn/html/multimedia_and_embedding/mozilla_splash_page/index.html @@ -0,0 +1,114 @@ +--- +title: Mozilla醒目页面 +slug: Learn/HTML/Multimedia_and_embedding/Mozilla_splash_page +tags: + - 初学者 + - 响应式 + - 图像 + - 多媒体 + - 嵌入 + - 视频 + - 评估 +translation_of: Learn/HTML/Multimedia_and_embedding/Mozilla_splash_page +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenu("Learn/HTML/Multimedia_and_embedding/Responsive_images", "Learn/HTML/Multimedia_and_embedding")}}</div> + +<p class="summary">在这个测验中,我们将测试你对于本模块文章所讨论的技术的掌握程度,让你将一些有关于 Mozilla 的图片和视频添加到一个漂亮的页面上!</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">学习本章节的要求:</th> + <td>在开始这个测验之前,你应该了解了 <a href="https://developer.mozilla.org/zh-CN/docs/Learn/HTML/Multimedia_and_embedding">多媒体与嵌入</a> 模块的其他文章.</td> + </tr> + <tr> + <th scope="row">目的:</th> + <td>测试这些知识的掌握程度:在页面中嵌入图片和视频,框架,和 HTML 响应式图片技术。</td> + </tr> + </tbody> +</table> + +<h2 id="起点">起点</h2> + +<p>为了开始这次测验,你需要从 <a href="https://github.com/roy-tian/learning-area/tree/master/html/multimedia-and-embedding/mdn-splash-page-start">mdn-splash-page-start</a> 这个GitHub目录下下载HTML和图片。保存在你本地设备上。</p> + +<p>访问 <a href="https://github.com/roy-tian/learning-area/tree/master/html/multimedia-and-embedding/mdn-splash-page-start/originals">originals</a> 文件夹中不同的图片文件,然后用同样的方法将它们下载到本地。现在,你需要将这些图片文件保存到不同的目录下,因为在这些图片准备好被使用之前,你需要使用图像编辑器来处理这些图片.</p> + +<div class="note"> +<p><strong>注意</strong>: 这个示例的 HTML 文件包含一些页面的 CSS 样式。你不需要去碰 CSS 的内容,而只是 {{htmlelement("body")}} 元素中的 HTML 部分,只要你插入了正确的标记,样式就会正确显示。</p> +</div> + +<h2 id="项目概要">项目概要</h2> + +<p>在这个测验中,我们为你呈现了一个接近完成了的 Mozilla醒目页面,旨在说明一些关于Mozilla的有趣的事情,以及提供一些更一步的资源链接。但目前还没有添加任何视频或图片,这份工作就交给你了!你需要添加一些图片、视频等多媒体元素,好让页面变得更漂亮和更有意义。下一小节详细描述了你需要做的工作:</p> + +<h3 id="准备图片">准备图片</h3> + +<p>使用你最爱的图片编辑器,创建下面几张图片的 400px 宽的版本和 120px 宽的版本:</p> + +<ul> + <li><code>firefox_logo-only_RGB.png</code></li> + <li><code>firefox-addons.jpg</code></li> + <li><code>mozilla-dinosaur-head.png</code></li> +</ul> + +<p>给它们取个有意义的名字,例如<code>firefoxlogo400.png</code> 和<code>firefoxlogo120.png</code>。</p> + +<p>这些图片将和 <code>mdn.svg</code> 一起作为<code>further-info</code>区内资源链接的图标和网站页眉的火狐图标。将这些图片副本保存在与 <code>index.html</code>文件的同一个目录下。 </p> + +<p>接着,创建一个 1200px 宽的 <code>red-panda.jpg</code>风景图片版本,和一个 600px 宽的肖像版本,用来显示更近镜头下的熊猫. 同样地,为它们取一个你可以轻松分辨出来的名字. 将它们的副本保存在与 <code>index.html</code>文件相同的目录下。</p> + +<div class="note"> +<p><strong>注意</strong>:你应该在看起来还行的前提下尽量优化 JPG 和 PNG 图片的大小,<a href="https://tinypng.com/">tinypng.com</a>为此提供了很好的服务。</p> +</div> + +<h3 id="为_header_添加一个图标">为 header 添加一个图标</h3> + +<p>在 {{htmlelement("header")}} 元素中添加一个 {{htmlelement("img")}} 元素,嵌入一个小尺寸版本的火狐图标。</p> + +<h3 id="为主_article_添加一个视频">为主 article 添加一个视频</h3> + +<p>就在 {{htmlelement("article")}} 元素中(开放标签下面),嵌入一个 Bilibili 视频(<a href="https://www.bilibili.com/video/BV1rs411d7hC?p=2">https://www.bilibili.com/video/BV1rs411d7hC?p=2</a>),使用 Bilibili 生成嵌入代码。视频的宽度应该是 400px。</p> + +<h3 id="为_further_info_的链接添加响应式图片">为 further info 的链接添加响应式图片</h3> + +<p>在<code>further-info</code>类的 {{htmlelement("div")}}里你会看到四个 {{htmlelement("a")}} 元素,每个都指向一个有趣的、关于 Mozilla 的页面。为了完成这一部分,你需要在每个{{htmlelement("a")}} 元素里插入一个 {{htmlelement("img")}} 元素,需要包含合适的 {{htmlattrxref("src", "img")}},{{htmlattrxref("alt", "img")}},{{htmlattrxref("srcset", "img")}} 和 {{htmlattrxref("sizes", "img")}} 属性。</p> + +<p>我们希望每张图片(除了某个本身就是响应式的)在浏览器的视口的宽度小于等于480px时使用的120px宽的图片,其他情况下选择400px 的版本.</p> + +<p>确保正确的链接匹配了正确的图片!</p> + +<div class="note"> +<p><strong>注意</strong>: 为了正确的测试 <code>srcset</code>/<code>sizes</code> 示例,你需要把你的网站上传到服务器(使用 <a href="/zh-CN/docs/Learn/Common_questions/Using_Github_pages">Github pages</a> 是一个简单免费的方法),访问服务器上的网页,你就可以使用浏览器开发者工具来测试它们是否正常工作,如 <a href="/zh-CN/Learn/HTML/Multimedia_and_embedding/Responsive_images#Useful_developer_tools">响应式图片:有用的开发工具</a>中所说</p> +</div> + +<h3 id="一张小熊猫的艺术照">一张小熊猫的艺术照</h3> + +<p>在<code>red-panda</code>类的{{htmlelement("div")}} 中,我们希望插入一个{{htmlelement("picture")}}元素,在视口宽度小于等于600px时使用那张比较小的纵向的熊猫图片,在其他情况下则使用大的横向的图片。</p> + +<h2 id="示例">示例</h2> + +<p>下面的截图展示了在正确标记后,醒目页面在宽屏和窄屏下的样子。(可 <a class="external external-icon" href="https://roy-tian.github.io/learning-area/html/multimedia-and-embedding/mdn-splash-page-finished/">在线查看</a>)</p> + +<p><img alt="A wide shot of our example splash page" src="https://mdn.mozillademos.org/files/12946/wide-shot.png" style="border-style: solid; border-width: 1px; display: block; height: 620px; margin: 0px auto; width: 700px;"></p> + +<p><img alt="A narrow shot of our example splash page" src="https://mdn.mozillademos.org/files/12944/narrow-shot.png" style="border-style: solid; border-width: 1px; display: block; height: 1069px; margin: 0px auto; width: 320px;"></p> + +<h2 id="评估">评估</h2> + +<p>如果这个评估是一系列课程的一部分,你应该可以让你的老师或导师为你批改。 如果你是自学,可以很容易地在 <a href="https://discourse.mozilla.org/t/mozilla-splash-page-assignment/24679">discussion thread about this exercise</a>或<a href="https://wiki.mozilla.org/IRC" rel="noopener">Mozilla IRC</a>的<a href="irc://irc.mozilla.org/mdn">#mdn</a> IRC频道回复得到批改指南。请先自己试着做——作弊学不到任何东西!</p> + +<h2 id="在这个模块中">在这个模块中</h2> + +<ul> + <li><a href="https://developer.mozilla.org/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/Images_in_HTML">HTML中的图片</a></li> + <li><a href="https://developer.mozilla.org/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/Video_and_audio_content">音视频内容</a></li> + <li><a href="https://developer.mozilla.org/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies" rel="nofollow">从<object> 到<iframe> — 其他嵌入技术</a></li> + <li><a href="https://developer.mozilla.org/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web">给网页添加矢量图</a></li> + <li><a href="https://developer.mozilla.org/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images">响应式图片</a></li> + <li><a href="https://developer.mozilla.org/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/Mozilla_splash_page">Mozilla醒目页面</a></li> +</ul> + +<p>{{PreviousMenu("Learn/HTML/Multimedia_and_embedding/Responsive_images", "Learn/HTML/Multimedia_and_embedding")}}</p> diff --git a/files/zh-cn/learn/html/multimedia_and_embedding/responsive_images/index.html b/files/zh-cn/learn/html/multimedia_and_embedding/responsive_images/index.html new file mode 100644 index 0000000000..4a5ab10f21 --- /dev/null +++ b/files/zh-cn/learn/html/multimedia_and_embedding/responsive_images/index.html @@ -0,0 +1,259 @@ +--- +title: 响应式图片 +slug: Learn/HTML/Multimedia_and_embedding/Responsive_images +translation_of: Learn/HTML/Multimedia_and_embedding/Responsive_images +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web", "Learn/HTML/Multimedia_and_embedding/Mozilla_splash_page", "Learn/HTML/Multimedia_and_embedding")}}</div> + +<div> +<p class="summary">在这篇文章中我们将学习关于响应式图片——一种可以在不同的屏幕尺寸和分辨率的设备上都能良好工作以及其他特性的图片,并且看看HTML提供了什么工具来帮助实现它们。响应式图片仅仅只是响应式web设计的一部分(奠定了响应式web设计的良好基础),我们会在未来的<a href="/en-US/docs/Learn/CSS">CSS topic</a>模块中学到更多关于这一主题的知识。</p> +</div> + +<table class="learn-box nostripe standard-table"> + <tbody> + <tr> + <th scope="row">学习本章节的前提:</th> + <td>你应该已经了解了 <a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML">HTML的基础</a> 以及如何 <a href="/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/Images_in_HTML">在网站上添加静态图片</a>.</td> + </tr> + <tr> + <th scope="row">目的:</th> + <td>学习如何使用 {{htmlattrxref("srcset", "img")}} 以及 {{htmlelement("picture")}} 元素,来实现网页中的响应式图片处理方法。</td> + </tr> + </tbody> +</table> + +<h2 id="为什么要用自适应的图片?">为什么要用自适应的图片?</h2> + +<p>让我们来看一个典型的场景。一个典型的网站可能会有一张页首图片,这让访问者看起来感到愉快。图片下面可能会添加一些内容图像。页首图像的跨度可能是整个页首的宽度。而内容图像会适应内容纵列的某处。此处有个简单的例子:</p> + +<p><img alt="Our example site as viewed on a wide screen - here the first image works ok, as it is big enough to see the detail in the center." src="https://mdn.mozillademos.org/files/12940/picture-element-wide.png" style="display: block; height: 554px; margin: 0px auto; width: 700px;"></p> + +<p>这个网页在宽屏设备上表现良好,例如笔记本电脑或台式机(你可以<a href="http://mdn.github.io/learning-area/html/multimedia-and-embedding/responsive-images/not-responsive.html">查看在线演示</a>并且在GitHub上查看<a href="https://github.com/mdn/learning-area/blob/master/html/multimedia-and-embedding/responsive-images/not-responsive.html">源代码</a>)。我们不会在这一节课中讨论CSS,除了下面提到的那些:</p> + +<ul> + <li>正文内容被设置的最大宽度为1200像素——在高于该宽度的可视窗口中,正文保持在1200像素,并将其本身置于可用空间的中间。在该宽度以下的可视窗口中,正文将保持在可视窗口宽度的100%。</li> + <li>页眉图像被设置为使其中心始终位于页眉的中心,无论页眉的宽度是多少。所以如果网站被显示在窄屏上,图片中心的重要细节(里面的人)仍然可以看到,而两边超出的部分都消失了。它的高度是200px。</li> + <li>内容图片已经被设置为如果body元素比图像更小,图像就开始缩小,这样图像总是在正文里,而不是溢出正文。</li> +</ul> + +<p>然而,当你尝试在一个狭小的屏幕设备上查看本页面时,问题就会产生。网页的页眉看起来还可以,但是页眉这张图片占据了屏幕的一大部分的高度,在这个尺寸下,你很难看到在第一张图片内容里的人。</p> + +<p><img alt="Our example site as viewed on a narrow screen; the first image has shrunk to the point where it is hard to make out the detail on it." src="https://mdn.mozillademos.org/files/12936/non-responsive-narrow.png" style="display: block; height: 793px; margin: 0px auto; width: 320px;"></p> + +<p>一个改进的方法是,当网站在狭窄的屏幕上观看时,显示一幅图片的包含了重要细节的裁剪版本,第二个被裁剪的图片会在像平板电脑这样的中等宽度的屏幕设备上显示,这就是众所周知的<strong>美术设计问题(art direction problem)</strong>。</p> + +<p>另外,如果是在小屏手机屏幕上显示网页,那么没有必要在网页上嵌入这样大的图片。这被称之为<strong>分辨率切换问题(resolution switching problem)</strong>。位图有固定数量的像素宽,固定数量的像素高,与 <a href="https://developer.mozilla.org/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web">矢量图</a> 外观相同,但本质不同。如果显示尺寸大于原始尺寸,一张自身较小的位图看起来会有颗粒感(矢量图则不会)。</p> + +<p>相反,没有必要在比图片实际尺寸小的屏幕上显示一张大图,这样做会浪费带宽——当可以在设备上使用小图像时,手机用户尤其不愿意因为下载用于桌面的大图像而浪费带宽。理想的情况是当访问网站时依靠不同的设备来提供不同的分辨率图片和不同尺寸的图片。</p> + +<p>让事情变得复杂的是,有些设备有很高的分辨率,为了显示的更出色,可能需要超出你预料的更大的图像。这从本质上是一样的问题,但在环境上有一些不同。</p> + +<p>你可能会认为矢量图形能解决这些问题,在某种程度上是这样的——它们无论是文件大小还是比例都合适,无论在哪里你都应该尽可能的使用它们。然而,它们并不适合所有的图片类型,虽然在简单图形、图案、界面元素等方面较好,但如果是有大量的细节的照片,创建矢量图像会变得非常复杂。像JPEG格式这样的位图会更适合上面例子中的图像。</p> + +<p>当web第一次出现时,这样的问题并不存在,在上世纪90年代中期,仅仅可以通过笔记本电脑和台式机来浏览web页面,所以浏览器开发者和规范制定者甚至没有想到要实现这种解决方式(响应式开发)。最近应用的响应式图像技术,通过让浏览器提供多个图像文件来解决上述问题,比如使用相同显示效果的图片但包含多个不同的分辨率(分辨率切换),或者使用不同的图片以适应不同的空间分配(美术设计)。</p> + +<div class="note"> +<p><strong>注意</strong>: 在这篇文章中讨论的新特性 — {{htmlattrxref("srcset", "img")}}/{{htmlattrxref("sizes", "img")}}/{{htmlelement("picture")}} — 都已经被新版本的现代浏览器和移动浏览器所支持(包括Edge,而不是IE)。</p> +</div> + +<h2 id="怎样创建自适应的图片">怎样创建自适应的图片?</h2> + +<p>在这一部分中,我们将看看上面说明的两个问题,并且展示怎样用HTML的响应式图片来解决这些问题。需要注意的是,如以上示例所示,在本节中我们将专注于HTML的 {{htmlelement("img")}},但网站页眉的图片仅是装饰性的,实际上应该要用CSS的背景图片来实现。<a href="http://blog.cloudfour.com/responsive-images-101-part-8-css-images/">CSS是比HTML更好的响应式设计的工具</a>,我们会在未来的CSS模块中讨论。</p> + +<h3 id="分辨率切换:不同的尺寸">分辨率切换:不同的尺寸</h3> + +<p>那么,我们想要用分辨率切换解决什么问题呢?我们想要显示相同的图片内容,仅仅依据设备来显示更大或更小的图片——这是我们在示例中使用第二个内容图像的情况。标准的{{htmlelement("img")}}元素传统上仅仅让你给浏览器指定唯一的资源文件。</p> + +<pre class="brush: html notranslate"><img src="elva-fairy-800w.jpg" alt="Elva dressed as a fairy"></pre> + +<p>我们可以使用两个新的属性——{{htmlattrxref("srcset", "img")}} 和 {{htmlattrxref("sizes", "img")}}——来提供更多额外的资源图像和提示,帮助浏览器选择正确的一个资源。你可以看到 <a href="http://mdn.github.io/learning-area/html/multimedia-and-embedding/responsive-images/responsive.html">responsive.html</a> 的例子,也可以在GitHub上看到<a href="https://github.com/mdn/learning-area/blob/master/html/multimedia-and-embedding/responsive-images/responsive.html">source code</a>:</p> + +<pre class="brush: html notranslate"><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"></pre> + +<p><code>srcset</code>和<code>sizes</code>属性看起来很复杂,但是如果你按照上图所示进行格式化,那么他们并不是很难理解,每一行有不同的属性值。每个值都包含逗号分隔的列表。列表的每一部分由三个子部分组成。让我们来看看现在的每一个内容:</p> + +<p><strong>srcset</strong>定义了我们允许浏览器选择的图像集,以及每个图像的大小。在每个逗号之前,我们写:</p> + +<ol> + <li>一个<strong>文件名 </strong>(<code>elva-fairy-480w.jpg</code>.)</li> + <li>一个空格</li> + <li><strong>图像的固有宽度</strong>(以像素为单位)(480w)——注意到这里使用<code>w</code>单位,而不是你预计的<code>px</code>。这是图像的真实大小,可以通过检查你电脑上的图片文件找到(例如,在Mac上,你可以在Finder上选择这个图像,然后按 <kbd>Cmd</kbd> + <kbd>I</kbd> 来显示信息)。</li> +</ol> + +<p><code><strong>sizes</strong></code>定义了一组媒体条件(例如屏幕宽度)并且指明当某些媒体条件为真时,什么样的图片尺寸是最佳选择—我们在之前已经讨论了一些提示。在这种情况下,在每个逗号之前,我们写:</p> + +<ol> + <li>一个<strong>媒体条件</strong>(<code>(max-width:480px)</code>)——你会在 <a href="/en-US/docs/Learn/CSS">CSS topic</a>中学到更多的。但是现在我们仅仅讨论的是媒体条件描述了屏幕可能处于的状态。在这里,我们说“当可视窗口的宽度是480像素或更少”。</li> + <li>一个空格</li> + <li>当媒体条件为真时,图像将填充的<strong>槽的宽度</strong>(<code>440px</code>)</li> +</ol> + +<div class="note"> +<p><strong>注意</strong>: 对于槽的宽度,你也许会提供一个固定值 (<code>px</code>, <code>em</code>) 或者是一个相对于视口的长度(<code>vw</code>),但不是百分比。你也许已经注意到最后一个槽的宽度是没有媒体条件的,它是默认的,当没有任何一个媒体条件为真时,它就会生效。 当浏览器成功匹配第一个媒体条件的时候,剩下所有的东西都会被忽略,所以要注意媒体条件的顺序。</p> +</div> + +<p>所以,有了这些属性,浏览器会:</p> + +<ol> + <li>查看设备宽度</li> + <li>检查<code>sizes</code>列表中哪个媒体条件是第一个为真</li> + <li>查看给予该媒体查询的槽大小</li> + <li>加载<code>srcset</code>列表中引用的最接近所选的槽大小的图像</li> +</ol> + +<p>就是这样!所以在这里,如果支持浏览器以视窗宽度为480px来加载页面,那么<code>(max-width: 480px)</code>的媒体条件为真,因此<code>440px</code>的槽会被选择,所以<code>elva-fairy-480w.jpg</code>将加载,因为它的的固定宽度(<code>480w</code>)最接近于<code>440px</code>。800px的照片大小为128KB而480px版本仅有63KB大小—节省了65KB。现在想象一下,如果这是一个有很多图片的页面。使用这种技术会节省移动端用户的大量带宽。</p> + +<p>老旧的浏览器不支持这些特性,它会忽略这些特征。并继续正常加载 {{htmlattrxref("src", "img")}}属性引用的图像文件。</p> + +<div class="note"> +<p><strong>注意</strong>: 在 HTML 文件中的 {{htmlelement("head")}} 标签里, 你将会找到这一行代码 <code><meta name="viewport" content="width=device-width"></code>: 这行代码会强制地让手机浏览器采用它们真实可视窗口的宽度来加载网页(有些手机浏览器会提供不真实的可视窗口宽度, 然后加载比浏览器真实可视窗口的宽度大的宽度的网页,然后再缩小加载的页面,这样的做法对响应式图片或其他设计,没有任何帮助。我们会在未来的模块教给你更多关于这方面的知识)。</p> +</div> + +<h3 id="一些有用的开发工具">一些有用的开发工具</h3> + +<p>这里有一些在浏览器中的非常实用的<a href="/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools">开发者工具</a>用来帮助制定重要的槽宽度,以及其他你可能会用到的场景。当我在设置槽宽度的时候,我先加载了示例中的无响应的版本(<code>not-responsive.html</code>),然后进入 <a href="/en-US/docs/Tools/Responsive_Design_Mode">响应设计视图</a> (<em>Tools > Web Developer > Responsive Design View),</em>这个工具允许你在不同设备的屏幕宽度场景下查看网页的布局。</p> + +<p>我设置我的视图宽度为 320px,然后再改为 480px;每一次宽度的改变我就进入 <a href="/en-US/docs/Tools/Page_Inspector">DOM 检查 </a>,点击我们感兴趣的 {{htmlelement("img")}} 元素,然后在显示屏右侧的 Box Model 视图选项卡中查看它的大小。 你应该会看到,这种无响应式的做法会让你的图片在不同屏幕宽度下有着固定的宽度。</p> + +<p><img alt="A screenshot of the firefox devtools with an image element highlighted in the dom, showing its dimensions as 440 by 293 pixels." src="https://mdn.mozillademos.org/files/12932/box-model-devtools.png" style="display: block; height: 845px; margin: 0px auto; width: 480px;"></p> + +<p>接着, 你可以检查 <code>srcset</code> 是否正常工作,你需要将视图的宽度设置为你想要的,(比如,把宽度设置的比较小,让页面看起来比较狭窄),打开网络检查(<em>Tools > Web Developer > Network),</em>然后重新加载页面。网络检查工具会给你一个列表,里面的文件都是已经被下载来构造网页的。然后你可以在这里看到哪个图像文件被下载了。</p> + +<div class="note"> +<p><strong>注意</strong>: 在 Chrome 中测试时,通过如下方式禁用缓存:打开 DevTools ,并选中 Settings > Preferences > Network下Disable cache的选择框。否则,Chrome 会优先选择缓存图片而不是恰好适配的那个。</p> +</div> + +<p><img alt="a screenshot of the network inspector in firefox devtools, showing that the HTML for the page has been downloaded, along with three images, which include the two 800 wide versions of the responsive images" src="https://mdn.mozillademos.org/files/12934/network-devtools.png" style="display: block; height: 630px; margin: 0px auto; width: 600px;"></p> + +<h3 id="分辨率切换_相同的尺寸_不同的分辨率">分辨率切换: 相同的尺寸, 不同的分辨率</h3> + +<p>如果你支持多种分辨率显示,但希望每个人在屏幕上看到的图片的实际尺寸是相同的,你可以让浏览器通过<code>srcset</code>和x语法结合——一种更简单的语法——而不用<code>sizes</code>,来选择适当分辨率的图片。你可以看一个例子 <a href="https://mdn.github.io/learning-area/html/multimedia-and-embedding/responsive-images/srcset-resolutions.html">srcset-resolutions.html</a>(或 <a href="https://github.com/mdn/learning-area/blob/master/html/multimedia-and-embedding/responsive-images/srcset-resolutions.html">the source code</a>):</p> + +<pre class="brush: html notranslate"><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"> +</pre> + +<p><img alt="A picture of a little girl dressed up as a fairy, with an old camera film effect applied to the image" src="https://mdn.mozillademos.org/files/12942/resolution-example.png" style="display: block; height: 425px; margin: 0px auto; width: 480px;">在这个例子中,下面的CSS会应用在图片上,所以它的宽度在屏幕上是320像素(也称作CSS像素):</p> + +<pre class="brush: css notranslate">img { + width: 320px; +}</pre> + +<p>在这种情况下,<code>sizes</code>并不需要——浏览器只是计算出正在显示的显示器的分辨率,然后提供<code>srcset</code>引用的最适合的图像。因此,如果访问页面的设备具有标准/低分辨率显示,一个设备像素表示一个CSS像素,<code>elva-fairy-320w.jpg</code>会被加载(1x 是默认值,所以你不需要写出来)。如果设备有高分辨率,两个或更多的设备像素表示一个CSS像素,<code>elva-fairy-640w.jpg</code> 会被加载。640px的图像大小为93KB,320px的图像的大小仅仅有39KB。</p> + +<h3 id="美术设计">美术设计</h3> + +<p>回顾一下,<strong>美术设计问题</strong>涉及要更改显示的图像以适应不同的图像显示尺寸。例如,如果在桌面浏览器上的一个网站上显示一张大的、横向的照片,照片中央有个人,然后当在移动端浏览器上浏览这个网站时,照片会缩小,这时照片上的人会变得非常小,看起来会很糟糕。这种情况可能在移动端显示一个更小的肖像图会更好,这样人物的大小看起来更合适。{{htmlelement("picture")}}元素允许我们这样实现。</p> + +<p>回到我们最初的例子 <a href="http://mdn.github.io/learning-area/html/multimedia-and-embedding/responsive-images/not-responsive.html">not-responsive.html</a> ,我们有一张图片需要美术设计:</p> + +<pre class="brush: html notranslate"><img src="elva-800w.jpg" alt="Chris standing up holding his daughter Elva"></pre> + +<p>让我们改用 {{htmlelement("picture")}}!就像<a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Video_and_audio_content"><code><video></code>和<code><audio></code></a>,{{htmlelement("picture")}}素包含了一些{{htmlelement("source")}}元素,它使浏览器在不同资源间做出选择,紧跟着的是最重要的{{htmlelement("img")}}元素。<a href="http://mdn.github.io/learning-area/html/multimedia-and-embedding/responsive-images/responsive.html">responsive.html</a> 的代码如下:</p> + +<pre class="brush: html notranslate"><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> +</pre> + +<ul> + <li> <code><source></code>元素包含一个<code>media</code>属性,这一属性包含一个媒体条件——就像第一个<code>srcset</code>例子,这些条件来决定哪张图片会显示——第一个条件返回真,那么就会显示这张图片。在这种情况下,如果视窗的宽度为799px或更少,第一个<code><source></code>元素的图片就会显示。如果视窗的宽度是800px或更大,就显示第二张图片。</li> + <li><code>srcset</code>属性包含要显示图片的路径。请注意,正如我们在<code><img></code>上面看到的那样,<code><source></code>可以使用引用多个图像的<code>srcset</code>属性,还有<code>sizes</code>属性。所以你可以通过一个 <code><picture></code>元素提供多个图片,不过也可以给每个图片提供多分辨率的图片。实际上,你可能不想经常做这样的事情。</li> + <li>在任何情况下,你都必须在 <code></picture></code>之前正确提供一个<code><img></code>元素以及它的<code>src</code>和<code>alt</code>属性,否则不会有图片显示。当媒体条件都不返回真的时候(你可以在这个例子中删除第二个<code><source></code> 元素),它会提供图片;如果浏览器不支持 <code><picture></code>元素时,它可以作为后备方案。</li> +</ul> + +<p>这样的代码允许我们在宽屏和窄屏上都能显示合适的图片,像下面展示的一样:</p> + +<p><img alt="Our example site as viewed on a wide screen - here the first image works ok, as it is big enough to see the detail in the center." src="https://mdn.mozillademos.org/files/12940/picture-element-wide.png" style="display: block; height: 554px; margin: 0px auto; width: 700px;"><img alt="Our example site as viewed on a narrow screen with the picture element used to switch the first image to a portrait close up of the detail, making it a lot more useful on a narrow screen" src="https://mdn.mozillademos.org/files/12938/picture-element-narrow.png" style="display: block; height: 710px; margin: 0px auto; width: 320px;"></p> + +<div class="note"> +<p><strong>注意</strong>: 你应该仅仅当在美术设计场景下使用media属性;当你使用media时,不要在sizes属性中也提供媒体条件。</p> +</div> + +<h3 id="为什么我们不能使用_CSS_或_JavaScript_来做到这一效果">为什么我们不能使用 CSS 或 JavaScript 来做到这一效果?</h3> + +<p>当浏览器开始加载一个页面, 它会在主解析器开始加载和解析页面的 CSS 和 JavaScript 之前先下载 (预加载) 任意的图片。这是一个非常有用的技巧,平均下来减少了页面加载时间的20%。但是, 这对响应式图片一点帮助都没有, 所以需要类似 <code>srcset</code>的实现方法。因为你不能先加载好 {{htmlelement("img")}} 元素后, 再用 JavaScript 检测可视窗口的宽度,如果觉得大小不合适,再动态地加载小的图片替换已经加载好的图片,这样的话, 原始的图像已经被加载了, 然后你又加载了小的图像, 这样的做法对于响应式图像的理念来说,是很糟糕的。</p> + +<ul> +</ul> + +<h3 id="大胆的使用现代图像格式">大胆的使用现代图像格式</h3> + +<p>有很多令人激动的新图像格式(例如WebP和JPEG-2000)可以在有高质量的同时有较低的文件大小。然而,浏览器对其的支持参差不齐。</p> + +<p><code><picture></code>让我们能继续满足老式浏览器的需要。你可以在<code>type</code>属性中提供MIME类型,这样浏览器就能立即拒绝其不支持的文件类型:</p> + +<pre class="brush: html notranslate"><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> +</pre> + +<ul> + <li>不要使用<code>media</code>属性,除非你也需要美术设计。</li> + <li>在<code><source></code> 元素中,你只可以引用在<code>type</code>中声明的文件类型。</li> + <li>像之前一样,如果必要,你可以在<code>srcset</code>和<code>sizes</code>中使用逗号分割的列表。</li> +</ul> + +<h2 id="主动学习:实现属于你的响应式图像">主动学习:实现属于你的响应式图像</h2> + +<p>在这次主动学习中,我们希望你变得勇敢和自力更生……尽量的。我们希望你通过使用<picture>来实现自己美术设计上的宽/窄屏显示适配,以及使用 <code>srcset</code>切换不同的分辨率。</p> + +<ol> + <li>写一些简单 HTML 来包含你的代码(如果你喜欢,也可以使用 <code>not-responsive.html</code> 作为起点)。</li> + <li>找一张漂亮的宽屏风景图像,其中需要包含一些细节。使用图像编辑器创建一个网页大小的版本。然后裁剪一下,显示一个更小的部分,其中包含放大的细节, 然后创建第二张图片 (差不多 480px 宽度比较好。)</li> + <li>使用 <code><picture></code> 元素来实现艺术图片切换器!</li> + <li>创建不同大小的多张图片, 每个图片的图像都是一样的。</li> + <li>使用 <code>srcset</code>/<code>size</code> 来创建一个分辨率切换器示例, 可以在不同的分辨率的情况下,提供相同尺寸的图像, 或者在不同的视图大小的情况下,提供不同尺寸大小的图像。</li> +</ol> + +<div class="note"> +<p><strong>注意</strong>: 使用浏览器开发工具来帮助你工作时可以得到你需要的视图大小,就像上文提到的。</p> +</div> + +<h2 id="小结">小结</h2> + +<p>这章节中充满了响应式图像 — 我们希望你学习新技术的过程是享受的。概括来说,有两个不同的问题,文章中我们一直在讨论:</p> + +<ul> + <li><strong>美术设计</strong>:当你想为不同布局提供不同剪裁的图片——比如在桌面布局上显示完整的、横向图片,而在手机布局上显示一张剪裁过的、突出重点的纵向图片,可以用 {{htmlelement("picture")}} 元素来实现。</li> + <li><strong>分辨率切换</strong>:当你想要为窄屏提供更小的图片时,因为小屏幕不需要像桌面端显示那么大的图片;以及你想为高/低分辨率屏幕提供不同分辨率的图片时,都可以通过 <a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web">vector graphics</a> (SVG images)、 {{htmlattrxref("srcset", "img")}} 以及 {{htmlattrxref("sizes", "img")}} 属性来实现。</li> +</ul> + +<p>此时整个<a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding">多媒体与嵌入</a> 模块接近尾声!在继续下一个模块之前,你现在唯一要做的就是尝试我们的多媒体评估,看看你做得怎样。玩的开心。</p> + +<h2 id="另请参阅">另请参阅</h2> + +<ul> + <li><a href="http://blog.cloudfour.com/responsive-images-101-definitions">Jason Grigsby对响应式图片的出色介绍</a></li> + <li><a href="https://css-tricks.com/responsive-images-youre-just-changing-resolutions-use-srcset/">R响应式图片:如果你只是在改变分辨率,就用srcset</a> — 包含了更多关于浏览器如何选择显示图片的解释</li> + <li>{{htmlelement("img")}}</li> + <li>{{htmlelement("picture")}}</li> + <li>{{htmlelement("source")}}</li> +</ul> + +<p>{{PreviousMenuNext("Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web", "Learn/HTML/Multimedia_and_embedding/Mozilla_splash_page", "Learn/HTML/Multimedia_and_embedding")}}</p> + +<h2 id="本章目录">本章目录</h2> + +<ul> + <li><a href="/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/Images_in_HTML">HTML 中的图片</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/Video_and_audio_content">视频和音频内容</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies">从 <code><object></code> 到 <code><iframe></code>:其它嵌入技术</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web">为网页添加向量图形</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images">响应式图片</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/Mozilla_splash_page">Mozilla 宣传页面</a></li> +</ul> diff --git a/files/zh-cn/learn/html/multimedia_and_embedding/video_and_audio_content/index.html b/files/zh-cn/learn/html/multimedia_and_embedding/video_and_audio_content/index.html new file mode 100644 index 0000000000..8fa670c5a3 --- /dev/null +++ b/files/zh-cn/learn/html/multimedia_and_embedding/video_and_audio_content/index.html @@ -0,0 +1,341 @@ +--- +title: 视频和音频内容 +slug: Learn/HTML/Multimedia_and_embedding/Video_and_audio_content +tags: + - 多媒体 + - 字幕 + - 指南 + - 文章 + - 新手 + - 视频 + - 音频 +translation_of: Learn/HTML/Multimedia_and_embedding/Video_and_audio_content +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/HTML/Multimedia_and_embedding/Images_in_HTML", "Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies", "Learn/HTML/Multimedia_and_embedding")}}</div> + +<p class="summary">现在我们可以轻松的为一个网页添加简单的图像,下一步我们开始为 HTML 文档添加音频和视频播放器。在这篇文章中,我们会使用 {{htmlelement("video")}} 和 {{htmlelement("audio")}} 元素来做到这件事;然后我们还会看看如何为你的视频添加字幕。</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">预备知识:</th> + <td>基础计算机能力,<a href="/zh-CN/docs/Learn/Getting_started_with_the_web/Installing_basic_software">基础的软件安装</a>,基础的<a href="/zh-CN/docs/Learn/Getting_started_with_the_web/Dealing_with_files">文件处理</a>知识,基础的 HTML 知识 (阅读 <a href="/zh-CN/docs/learn/HTML/Introduction_to_HTML/Getting_started">开始学习 HTML</a> ) 以及 <a href="/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/Images_in_HTML">HTML 中的图片</a>。</td> + </tr> + <tr> + <th scope="row">学习目标:</th> + <td>学习如何在一个网页中嵌入音频和视频,以及如何为视频添加字幕。</td> + </tr> + </tbody> +</table> + +<h2 id="web_中的音频和视频">web 中的音频和视频</h2> + +<p>web 开发者们一直以来想在 Web 中使用音频和视频,自21世纪初以来,我们的带宽开始能够支持任意类型的视频(视频文件比文本和图片要大的多)。在早些时候,传统的 web 技术(如 HTML )不能够在 Web 中嵌入音频和视频,所以一些像 <a href="https://en.wikipedia.org/wiki/Adobe_Flash">Flash</a> (后来有 <a href="https://en.wikipedia.org/wiki/Microsoft_Silverlight">Silverlight</a> ) 的专利技术在处理这些内容上变得很受欢迎。这些技术能够正常的工作,但是却有着一系列的问题,包括无法很好的支持 HTML/CSS 特性、安全问题,以及可行性问题。</p> + +<p>传统的解决方案能够解决许多这样的问题,前提是它能够正确的工作。幸运的是,几年之后 {{glossary("HTML5")}} 标准提出,其中有许多的新特性,包括 {{htmlelement("video")}} 和 {{htmlelement("audio")}} 标签,以及一些 {{Glossary("JavaScript")}} 和 {{Glossary("API","APIs")}} 用于对其进行控制。在这里,我们不讨论有关 JavaScript 的问题,仅仅讲解有关 HTML 的基础。</p> + +<p>我们不会教你如何制作音频和视频,因为那需要完全不同的技术。我们已经为你的试验提供了一些视频和音频的文件( <a href="https://github.com/mdn/learning-area/tree/master/html/multimedia-and-embedding/video-and-audio-content">sample audio and video files and example code</a> ),以防止你自己没有。</p> + +<div class="note"> +<p><strong>注意:</strong>在你开始之前,你应当了解一些 {{glossary("OVP","OVPs")}} (在线视频提供商) 例如 <a href="https://www.youtube.com/">YouTube</a> 、<a href="http://www.dailymotion.com">Dailymotion</a> 、<a href="https://vimeo.com/">Vimeo</a>、<a href="https://www.bilibili.com">Bilibili</a>等,以及在线音频提供商例如 <a href="https://soundcloud.com/">Soundcloud</a>。这些公司提供方便、简单的方式来支持视频,所以你不必担心庞大的带宽消耗。OVPS 甚至提供现成的代码用于为你的 web 网页嵌入视频/音频。如果你使用这样的服务,你便可以避免在这篇文章中我们将讨论的一些难题。在下一篇文章中,我们将会再讨论这样的服务。 </p> +</div> + +<h3 id="<video>_元素"><video> 元素</h3> + +<p>{{htmlelement("video")}} 允许你轻松地嵌入一段视频。一个简单的例子如下:</p> + +<pre class="brush: html notranslate"><video src="rabbit320.webm" controls> + <p>你的浏览器不支持 HTML5 视频。可点击<a href="rabbit320.mp4">此链接</a>观看</p> +</video></pre> + +<p>当中的一些属性如下:</p> + +<dl> + <dt>{{htmlattrxref("src","video")}}</dt> + <dd>同 {{htmlelement("img")}} 标签使用方式相同,<code>src</code> 属性指向你想要嵌入网页当中的视频资源,他们的使用方式完全相同。</dd> + <dt>{{htmlattrxref("controls","video")}}</dt> + <dd>用户必须能够控制视频和音频的回放功能。你可以使用 <code>controls</code> 来包含浏览器提供的控件界面,同时你也可以使用合适的 <a href="/en-US/docs/Web/API/HTMLMediaElement">JavaScript API</a> 创建自己的界面。界面中至少要包含开始、停止以及调整音量的功能。</dd> + <dt><code><video></code> 标签内的内容</dt> + <dd>这个叫做<strong>后备内容</strong> — 当浏览器不支持 <code><video></code> 标签的时候,就会显示这段内容,这使得我们能够对旧的浏览器提供回退内容。你可以添加任何后备内容,在这个例子中我们提供了一个指向这个视频文件的链接,从而使用户至少可以访问到这个文件,而不会局限于浏览器的支持。</dd> +</dl> + +<p>已嵌入视频文件的网页样式如下:</p> + +<p><img alt="A simple video player showing a video of a small white rabbit" src="https://mdn.mozillademos.org/files/12794/simple-video.png" style="display: block; height: 592px; margin: 0px auto; width: 589px;"></p> + +<p>你可以点击<a href="https://mdn.github.io/learning-area/html/multimedia-and-embedding/video-and-audio-content/simple-video.html">这里</a>查看网页,或者点击<a href="https://github.com/mdn/learning-area/blob/master/html/multimedia-and-embedding/video-and-audio-content/simple-video.html">这里</a>查看源代码。</p> + +<h3 id="使用多个播放源以提高兼容性">使用多个播放源以提高兼容性</h3> + +<p>以上的例子中有一个问题,你可能已经注意到了,如果你尝试使用像 Safari 或者 Internet Explorer 这些浏览器来访问上面的链接。视频并不会播放,这是因为不同的浏览器对视频格式的支持不同。幸运的是,你有办法防止这个问题发生。</p> + +<h4 id="媒体文件的内容">媒体文件的内容</h4> + +<p>我们先来快速的了解一下术语。像 MP3、MP4、WebM这些术语叫做<a href="https://wiki.developer.mozilla.org/en-US/docs/Web/Media/Formats/Containers">容器格式</a>。他们定义了构成媒体文件的音频轨道和视频轨道的储存结构,其中还包含描述这个媒体文件的元数据,以及用于编码的编码译码器等等。</p> + +<p>一个格式为 WebM 的电影包含视频轨道,音频轨道和文本轨道,其中视频轨道包含一个主视频轨道和一个可选的 Angle 轨道;音频轨道包含英语和西班牙语的音频轨道,还有一个英语评论的音频轨道;文字轨道包含英语和西班牙语的字幕轨道,如下图所示:</p> + +<p><img alt="Diagram conceptualizing the contents of a media file at the track level." src="https://mdn.mozillademos.org/files/16898/ContainersAndTracks.svg"></p> + +<p>为了编解码器(codec)编码媒体,容器中的音频和视频轨道以适合的格式保存。音频轨道和视频轨道使用不同的格式。每个音频轨道都使用<a href="https://wiki.developer.mozilla.org/en-US/docs/Web/Media/Formats/Audio_codecs">音频编解码器</a>进行编码,而视频轨道则使用(您可能已经猜到了)<a href="https://wiki.developer.mozilla.org/en-US/docs/Web/Media/Formats/Video_codecs">视频编解码器</a>进行编码。如前所述,不同的浏览器支持不同的视频和音频格式,以及不同的容器格式(如MP3、MP4和WebM,这些格式又可以包含不同类型的视频和音频)。</p> + +<p>例如:</p> + +<ul> + <li>WebM 容器通常包括了 Opus 或 Vorbis 音频和 VP8/VP9 视频。这在所有的现代浏览器中都支持,除了他们的老版本。</li> + <li>MP4 容器通常包括 AAC 以及 MP3 音频和 H.264 视频。这在所有的现代浏览器中都支持,还有 Internet Explorer。</li> + <li>老式的 Ogg 容器往往支持 Ogg Vorbis 音频和 Ogg Theora 视频。主要在 Firefox 和 Chrome 当中支持,不过这个容器已经被更强大的 WebM 容器所取代。</li> +</ul> + +<p>有一些特殊情况。例如,对于某些类型的音频,通常编解码器的数据存储没有容器或简化容器。其中一个例子就是FLAC编解码器,它通常存储在FLAC文件中,FLAC文件只是FLAC的原始轨迹。</p> + +<p>另一种情况是一直流行的MP3文件。“MP3文件”实际上是存储在MPEG或MPEG-2容器中的MPEG-1音频层III(MPEG-1 Audio Layer III ,MP3)音频轨道。这一点特别有趣,因为尽管大多数浏览器不支持在{{HTMLElement("video")}}和{{HTMLElement("audio")}}元素中使用MPEG媒体,但由于MP3的流行,它们可能仍然支持MP3。</p> + +<p>音频播放器将会直接播放音频文件,例如 MP3 和 Ogg 文件。这些不需要容器。</p> + +<h4 id="浏览器所支持的媒体文件">浏览器所支持的媒体文件</h4> + +<div class="callout-box"> +<p><strong>Note:</strong> 你也许会疑惑为什么会有这样的情况存在。<strong>MP3 </strong> (音频格式) 和 <strong>MP4/H.264</strong> (视频格式) 是被广泛支持的两种格式,并且质量良好。然而,他们却有专利的阻碍 — MP3 的专利会持续到2017年(就在我翻译这篇文章的当天,MP3专利解除了),而 H.264 会持续到2027年早期。意思也就是说浏览器若想要支持这些格式,就得支付高额的费用。此外,许多人反对软件技术垄断,支持开放的格式。这就是为什么我们需要准备不同的格式来兼容不同的浏览器。</p> +</div> + +<p>刚刚所说的格式主要用于将音频和视频压缩成可管理的文件(原始的音频和视频文件非常大)。浏览器包含了不同的 <strong>{{Glossary("Codec","Codecs")}}</strong>,,如 Vorbis 和 H.264,它们用来将已压缩的音频和视频转化成二进制数字。不同的编码器和不同的容器都有各自的优缺点,在你更了解它们后,你可以自己选择使用哪个编码器和容器。</p> + +<p>浏览器并不全支持相同的 codecs,所以你得使用几个不同格式的文件来兼容不同的浏览器。如果你使用的格式都得不到浏览器的支持,那么媒体文件将不会播放。</p> + +<p>要使你的媒体文件在不同平台,不同设备的浏览器上都可观看,这需要多种编码器组合使用,但是这是一种非常麻烦的事,所以可以参考{{SectionOnPage("/en-US/docs/Web/Media/Formats/Containers", "Choosing the right container")}}来选择最适合的容器格式,同样的,参考{{SectionOnPage("/en-US/docs/Web/Media/Formats/Video_codecs", "Choosing a video codec")}}和{{SectionOnPage("/en-US/docs/Web/Media/Formats/Audio_codecs", "Choosing an audio codec")}}选择编码格式</p> + +<p>需要记住的另一件事:同一款浏览器,移动版可能比桌面版权多支持的格式可能会有不同。最重要的是,它们都可以减轻媒体播放的处理负担(对于所有媒体或仅针对其内部无法处理的特定类型)。这意味着设备的媒体支持还部分取决于用户安装了什么软件。</p> + +<p><!-- 注:这并没有那么简单,你可以从这里看到 <a href="/zh-CN/docs/Web/HTML/Supported_media_formats#浏览器兼容情况">音视频编码兼容表</a>。此外,许多移动平台的浏览器能够播放一些不支持的格式,但是它们用的却是底层系统的媒体播放器。但这也仅是现在支持。--></p> + +<p>我们该怎么做呢?请看如下例子(你可以点击这里<a href="https://mdn.github.io/learning-area/html/multimedia-and-embedding/video-and-audio-content/multiple-video-formats.html">查看</a>网页,或者点击这里<a href="https://github.com/mdn/learning-area/blob/gh-pages/html/multimedia-and-embedding/video-and-audio-content/multiple-video-formats.html">查看</a>源代码):</p> + +<pre class="brush: html notranslate"><video controls> + <source src="rabbit320.mp4" type="video/mp4"> + <source src="rabbit320.webm" type="video/webm"> + <p>你的浏览器不支持 HTML5 视频。可点击<a href="rabbit320.mp4">此链接</a>观看</p> +</video></pre> + +<p>现在我们将 <code>src</code> 属性从 <code><video></code> 标签中移除,转而将它放在几个单独的标签 {{htmlelement("source")}} 当中。在这个例子当中,浏览器将会检查 <code><source></code> 标签,并且播放第一个与其自身 codec 相匹配的媒体。你的视频应当包括 WebM 和 MP4 两种格式,这两种在目前已经足够支持大多数平台和浏览器。</p> + +<p>每个 <code><source></code> 标签页含有一个 <code>type</code> 属性,这个属性是可选的,但是建议你添加上这个属性 — 它包含了视频文件的 {{glossary("MIME type","MIME types")}} ,同时浏览器也会通过检查这个属性来迅速的跳过那些不支持的格式。如果你没有添加 <code>type</code> 属性,浏览器会尝试加载每一个文件,直到找到一个能正确播放的格式,这样会消耗掉大量的时间和资源。</p> + +<div class="note"> +<p><strong>Note</strong>: 你可以在这里(<a href="/zh-CN/docs/Web/HTML/Supported_media_formats">HTML 媒体格式支持</a>)查看有关 {{glossary("MIME type","MIME types")}} 的支持。</p> +</div> + +<h3 id="其他_<video>_特性">其他 <video> 特性</h3> + +<p>这里有许多你可以用在 HTML5 <code><video></code> 上的特性,请看我们的第三个例子:</p> + +<pre class="brush: html notranslate"><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>你的浏览器不支持 HTML5 视频。可点击<a href="rabbit320.mp4">此链接</a>观看</p> +</video> +</pre> + +<p>这串代码将会给我们呈现出如下页面:</p> + +<p><img alt="A video player showing a poster image before it plays. The poster image says HTML5 video example, OMG hell yeah!" src="https://mdn.mozillademos.org/files/12796/extra-video-features.png" style="display: block; height: 731px; margin: 0px auto; width: 653px;">新的特性:</p> + +<dl> + <dt>{{htmlattrxref("width","video")}} 和 {{htmlattrxref("height","video")}}</dt> + <dd>你可以用属性控制视频的尺寸,也可以用 {{Glossary("CSS")}} 来控制视频尺寸。 无论使用哪种方式,视频都会保持它原始的长宽比 — 也叫做<strong>纵横比</strong>。如果你设置的尺寸没有保持视频原始长宽比,那么视频边框将会拉伸,而未被视频内容填充的部分,将会显示默认的背景颜色。</dd> + <dt>{{htmlattrxref("autoplay","video")}}</dt> + <dd>这个属性会使音频和视频内容立即播放,即使页面的其他部分还没有加载完全。建议不要应用这个属性在你的网站上,因为用户们会比较反感自动播放的媒体文件。</dd> + <dt>{{htmlattrxref("loop","video")}}</dt> + <dd>这个属性可以让音频或者视频文件循环播放。同样不建议使用,除非有必要。</dd> + <dt>{{htmlattrxref("muted","video")}}</dt> + <dd>这个属性会导致媒体播放时,默认关闭声音。</dd> + <dt>{{htmlattrxref("poster","video")}}</dt> + <dd>这个属性指向了一个图像的URL,这个图像会在视频播放前显示。通常用于粗略的预览或者广告。</dd> + <dt>{{htmlattrxref("preload","video")}}</dt> + <dd> + <p>这个属性被用来缓冲较大的文件,有3个值可选:</p> + + <ul> + <li><code>"none"</code> :不缓冲</li> + <li><code>"auto"</code> :页面加载后缓存媒体文件</li> + <li><code>"metadata"</code> :仅缓冲文件的元数据</li> + </ul> + </dd> +</dl> + +<p>你可以点击<a href="https://mdn.github.io/learning-area/html/multimedia-and-embedding/video-and-audio-content/extra-video-features.html">这里</a>查看以上的例子,也可以点击<a href="https://github.com/mdn/learning-area/blob/gh-pages/html/multimedia-and-embedding/video-and-audio-content/extra-video-features.html">这里</a>查看源代码。注意我们并没有使用 autoplay 属性在这个版本的例子中 — 如果当页面一加载就开始播放视频的话,就不会看到 poster 属性的效果了。</p> + +<h3 id="<audio>_标签"><audio> 标签</h3> + +<p>{{htmlelement("audio")}} 标签与 {{htmlelement("video")}} 标签的使用方式几乎完全相同,有一些细微的差别比如下面的边框不同,一个典型的例子如下:</p> + +<pre class="brush: html notranslate"><audio controls> + <source src="viper.mp3" type="audio/mp3"> + <source src="viper.ogg" type="audio/ogg"> + <p>你的浏览器不支持 HTML5 音频,可点击<a href="viper.mp3">此链接</a>收听。</p> +</audio></pre> + +<p>这串代码将会产生如下的效果:</p> + +<p><img alt="A simple audio player with a play button, timer, volume control, and progress bar" src="https://mdn.mozillademos.org/files/12798/audio-player.png" style="display: block; height: 413px; margin: 0px auto; width: 626px;"></p> + +<div class="note"> +<p><strong>Note</strong>: 你可以点击这里<a href="http://mdn.github.io/learning-area/html/multimedia-and-embedding/video-and-audio-content/multiple-audio-formats.html">查看</a>以上例子,或者点击<a href="https://github.com/mdn/learning-area/blob/gh-pages/html/multimedia-and-embedding/video-and-audio-content/multiple-audio-formats.html">这里</a>查看源代码。</p> +</div> + +<p>音频播放器所占用的空间比视频播放器要小,由于它没有视觉部件 — 你只需要显示出能控制音频播放的控件。一些与 HTML5 <code><video></code> 的差异如下:</p> + +<ul> + <li>{{htmlelement("audio")}} 标签不支持 <code>width</code>/<code>height</code> 属性 — 由于其并没有视觉部件,也就没有可以设置 <code>width</code>/<code>height</code> 的内容。</li> + <li>同时也不支持 <code>poster</code> 属性 — 同样,没有视觉部件。</li> +</ul> + +<p>除此之外,<code><audio></code> 标签支持所有 <code><video></code> 标签拥有的特性 — 你可以回顾上面的章节来了解更多的有关信息。</p> + +<h3 id="重新播放媒体">重新播放媒体</h3> + +<p>任何时候,你都可以在 Javascript 中调用 {{domxref("HTMLMediaElement.load", "load()")}} 方法来重置媒体。如果有多个由 {{HTMLElement("source")}} 标签指定的媒体来源,浏览器会从选择媒体来源开始重新加载媒体。</p> + +<pre class="brush: js notranslate">const mediaElem = document.getElementById("my-media-element"); +mediaElem.load();</pre> + +<h3 id="音轨增删事件">音轨增删事件</h3> + +<p>你可以监控媒体元素中的音频轨道,当音轨被添加或删除时,你可以通过监听相关事件来侦测到。具体来说,通过监听 {{domxref("AudioTrackList")}} 对象的 {{event("addtrack")}} 事件(即 {{domxref("HTMLMediaElement.audioTracks")}} 对象),你可以及时对音轨的增加做出响应。</p> + +<pre class="brush: js notranslate">const mediaElem = document.querySelector("video"); +mediaElem.audioTracks.onaddtrack = function(event) { + audioTrackAdded(event.track); +} +</pre> + +<p>你可以在我们的 {{domxref("TrackEvent")}} 文档中找到更多有用的信息。</p> + +<h2 id="显示音轨文本">显示音轨文本</h2> + +<p>现在,我们将讨论一个略微先进的概念,这个概念将会十分的有用。许多人不想(或者不能)听到 Web 上的音频/视频内容,至少在某些情况下是这样的,比如:</p> + +<ul> + <li>许多人患有听觉障碍(通常来说是很难听清声音的人,或者聋人),所以他们不能听见音频中的声音。</li> + <li>另外的情况可能是由于人们并不能听音频,可能是因为他们在一个非常嘈杂的环境当中(比如在一个拥挤的酒吧内恰好赶上了球赛 ),也可能是由于他们并不想打扰到其他人(比如在一个十分安静的地方,例如图书馆)。</li> + <li>有一些人他们不说音频当中的语言,所以他们听不懂,因此他们想要一个副本或者是翻译来帮助他们理解媒体内容。</li> +</ul> + +<p>给那些听不懂音频语言的人们提供一个音频内容的副本岂不是一件很棒的事情吗?所以,感谢 HTML5 <code><video></code> 使之成为可能,有了 <a href="/en-US/docs/Web/API/Web_Video_Text_Tracks_Format">WebVTT</a> 格式,你可以使用 {{htmlelement("track")}} 标签。</p> + +<div class="note"> +<p><strong>Note</strong>: “副本”的意思是指,用文本记录下音频的内容。</p> +</div> + +<p>WebVTT 是一个格式,用来编写文本文件,这个文本文件包含了众多的字符串,这些字符串会带有一些元数据,它们可以用来描述这个字符串将会在视频中显示的时间,甚至可以用来描述这些字符串的样式以及定位信息。这些字符串叫做 <strong>cues </strong>,你可以根据不同的需求来显示不同的样式,最常见的如下:</p> + +<dl> + <dt>subtitles</dt> + <dd>通过添加翻译字幕,来帮助那些听不懂外国语言的人们理解音频当中的内容。</dd> + <dt>captions</dt> + <dd>同步翻译对白,或是描述一些有重要信息的声音,来帮助那些不能听音频的人们理解音频中的内容。</dd> + <dt>timed descriptions</dt> + <dd>将文字转换为音频,用于服务那些有视觉障碍的人。</dd> +</dl> + +<p>一个典型的 WebVTT 文件如下:</p> + +<pre class="eval line-numbers language-html notranslate"><code class="language-html">WEBVTT + +1 +00:00:22.230 --> 00:00:24.606 +第一段字幕 + +2 +00:00:30.739 --> 00:00:34.074 +第二段 + + ...</code> +</pre> + +<p>让其与 HTML 媒体一起显示,你需要做如下工作:</p> + +<ol> + <li>以 .vtt 后缀名保存文件。</li> + <li>用 {{htmlelement("track")}} 标签链接 .vtt 文件, <code><track></code> 标签需放在 <code><audio></code> 或 <code><video> 标签当中</code>,同时需要放在所有 <source> 标签之后。使用 {{htmlattrxref("kind","track")}} 属性来指明是哪一种类型,如 subtitles 、 captions 、 descriptions。然后,使用 {{htmlattrxref("srclang","track")}} 来告诉浏览器你是用什么语言来编写的 subtitles。</li> +</ol> + +<p>如下:</p> + +<pre class="brush: html notranslate"><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></pre> + +<p>上面这串代码会显示一段带有字幕的视频,如下:</p> + +<p><img alt='Video player with stand controls such as play, stop, volume, and captions on and off. The video playing shows a scene of a man holding a spear-like weapon, and a caption reads "Esta hoja tiene pasado oscuro."' src="https://mdn.mozillademos.org/files/7887/video-player-with-captions.png" style="display: block; height: 365px; margin: 0px auto; width: 593px;"></p> + +<p>如果你想了解更多细节,你可以阅读 <a href="/en-US/Apps/Build/Audio_and_video_delivery/Adding_captions_and_subtitles_to_HTML5_video">Adding captions and subtitles to HTML5 video</a>。在 Github 上你可以找到与本文相关的样例,他们由 Ian Devlin 编写,点击<a href="https://iandevlin.github.io/mdn/video-player-with-captions/">这里</a>可以查看该样例,或者点击<a href="https://github.com/iandevlin/iandevlin.github.io/tree/master/mdn/video-player-with-captions">这里</a>查看源代码。这个样例使用了 JavaScript 代码,它使得用户可以选择不同的字幕。注意,若想要显示字幕,你需要点击 "CC" 按钮,并且选择一种语言 — English, Deutsch, 或 Español。</p> + +<div class="note"> +<p><strong>Note</strong>: 文本轨道会使你的网站更容易被搜索引擎抓取到 ({{glossary("SEO")}}), 由于搜索引擎的文本抓取能力非常强大,使用文本轨道甚至可以让搜索引擎通过视频的内容直接链接。</p> +</div> + +<h2 id="实践学习:在你的网站上嵌入你自己的视频或音频。">实践学习:在你的网站上嵌入你自己的视频或音频。</h2> + +<p>在这个实践学习当中,我们希望你能够走出去,并且记录一些你自己的视频或者音频 — 如今,大多数手机都能够非常方便的记录视频或者音频,并且你可以将他们上传到你的电脑上面,你可以使用这些功能来记录你的视频或音频。在这时候,你可能需要做一些格式转换,如果是视频的话,你需要将它们转化为 WebM 或者 MP4 ,如果是音频的话,你需要将它们转化为 MP3 或者 Ogg 。 不过你并不需要担心,有许多的程序都能够帮你解决这些问题,例如 <a href="http://www.mirovideoconverter.com/">Miro Video Converter</a> 和 <a href="https://sourceforge.net/projects/audacity/">Audacity</a>。我们非常希望你能够亲自动手实现它。</p> + +<p>如果你无法取得任意的音频或者视频,你可以使用我们已经为你提供的样本(<a href="https://github.com/mdn/learning-area/tree/master/html/multimedia-and-embedding/video-and-audio-content">sample audio and video files</a>)。同时你也可以使用我们的代码来作为参考。</p> + +<p>我们希望你能够:</p> + +<ol> + <li>将你的音频或者视频文件保存在你电脑上的一个新目录中。</li> + <li>创建一个新的 HTML 文件在相同的路径下,命名为 index.html。</li> + <li>在页面上添加 <code><audio></code> 和 <code><video></code> 标签;并使用浏览器默认的控件来显示它们。</li> + <li>在当中添加 <code><source></code> 标签,并添加 <code>type</code> 属性,以便于浏览器能够找到其能够支持的格式并加载它。</li> + <li>在 <code><video></code> 标签中添加 <code>poster</code> 属性,这会显示在视频播放之前。</li> +</ol> + +<p>另外,你可以尝试研究一下文本音轨,试着为你的视频添加一些字幕。</p> + +<h2 id="测试你的技能!">测试你的技能!</h2> + +<p>恭喜你,你已经完成了这篇教程的学习,但你是否还记得教程里最重要的内容呢?在继续之前,你可以通过一些测试来验证你是否已经掌握了这些内容,请参见<a href="/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/Video_and_audio_content/Test_your_skills:_Multimedia_and_embedding">测试你的技能:内嵌多媒体</a>。需要注意倒是,这个测试中的第三个问题可能会需要一些之后讲到的技术,所以我们建议你尝试之前阅读一下<a href="/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/其他嵌入技术">下一篇教程</a>。</p> + +<h2 id="总结">总结</h2> + +<p>我们祝愿你可以沉浸在 Web 网站的音频和视频当中,下一篇文章,我们将会学习到另外一种在 web 页面中嵌入内容的方法,比如使用 {{htmlelement("iframe")}} 或者 {{htmlelement("object")}}。</p> + +<h2 id="相关资料">相关资料</h2> + +<ul> + <li>{{htmlelement("audio")}}</li> + <li>{{htmlelement("video")}}</li> + <li>{{htmlelement("source")}}</li> + <li>{{htmlelement("track")}}</li> + <li><a href="/en-US/Apps/Build/Audio_and_video_delivery/Adding_captions_and_subtitles_to_HTML5_video">Adding captions and subtitles to HTML5 video</a></li> + <li><a href="/en-US/docs/Web/Apps/Fundamentals/Audio_and_video_delivery">Audio and Video delivery</a>::这里面包含了许多使用 HTML 和 JavaScript 在页面中添加音频或视频的资料。</li> + <li><a href="/en-US/docs/Web/Apps/Fundamentals/Audio_and_video_manipulation">Audio and Video manipulation</a>: 这里面包含了许多使用 JavaScript 来控制音频或视频的资料。</li> + <li>Automated options to <a href="http://www.inwhatlanguage.com/blog/translate-video-audio/">translate multimedia</a>.</li> +</ul> + +<p>{{PreviousMenuNext("Learn/HTML/Multimedia_and_embedding/Images_in_HTML", "Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies", "Learn/HTML/Multimedia_and_embedding")}}</p> + +<h2 id="本章目录">本章目录</h2> + +<ul> + <li><a href="/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/Images_in_HTML">HTML 中的图片</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/Video_and_audio_content">视频和音频内容</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies">从 <code><object></code> 到 <code><iframe></code>:其它嵌入技术</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web">为网页添加向量图形</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images">响应式图片</a></li> + <li><a href="/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/Mozilla_splash_page">Mozilla 宣传页面</a></li> +</ul> + +<dl> +</dl> + +<ul> +</ul> diff --git a/files/zh-cn/learn/html/multimedia_and_embedding/video_and_audio_content/test_your_skills_colon__multimedia_and_embedding/index.html b/files/zh-cn/learn/html/multimedia_and_embedding/video_and_audio_content/test_your_skills_colon__multimedia_and_embedding/index.html new file mode 100644 index 0000000000..ace192f4d3 --- /dev/null +++ b/files/zh-cn/learn/html/multimedia_and_embedding/video_and_audio_content/test_your_skills_colon__multimedia_and_embedding/index.html @@ -0,0 +1,91 @@ +--- +title: 'Test your skills: Multimedia and embedding' +slug: >- + Learn/HTML/Multimedia_and_embedding/Video_and_audio_content/Test_your_skills:_Multimedia_and_embedding +translation_of: >- + Learn/HTML/Multimedia_and_embedding/Video_and_audio_content/Test_your_skills:_Multimedia_and_embedding +--- +<div>{{learnsidebar}}</div> + +<p>This aim of this skill test is to assess whether you've understood our <a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Video_and_audio_content">Video and audio content</a> and <a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies">From object to iframe — other embedding technologies</a> articles.</p> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: You can try out solutions in the interactive editors below, however it may be helpful to download the code and use an online tool such as <a href="https://codepen.io/">CodePen</a>, <a href="https://jsfiddle.net/">jsFiddle</a>, or <a href="https://glitch.com/">Glitch</a> to work on the tasks.<br> + <br> + If you get stuck, then ask us for help — see the {{anch("Assessment or further help")}} section at the bottom of this page.</p> +</div> + +<h2 id="Multimedia_and_embedding_1">Multimedia and embedding 1</h2> + +<p>In this task we want you to embed a simple audio file onto the page. You need to:</p> + +<ul> + <li>Add the path to the audio file to an appropriate attribute to embed it on the page. The audio is called <code>audio.mp3</code>, and it is in a folder inside the current folder called <code>media</code>.</li> + <li>Add an attribute to make browsers display some default controls.</li> + <li>Add some appropriate fallback text for browsers that don't support <code><audio></code>.</li> +</ul> + +<p>Try updating the live code below to recreate the finished example:</p> + +<p>{{EmbedGHLiveSample("learning-area/html/multimedia-and-embedding/tasks/media-embed/mediaembed1.html", '100%', 700)}}</p> + +<div class="blockIndicator note"> +<p><a href="https://github.com/mdn/learning-area/tree/master/html/multimedia-and-embedding/tasks/media-embed/mediaembed1-download.html">Download the starting point for this task</a> to work in your own editor or in an online editor.</p> +</div> + +<h2 id="Multimedia_and_embedding_2">Multimedia and embedding 2</h2> + +<p>In this task we want you to mark up a slightly more complex video player, with multiple sources, subtitles, and other features besides. You need to:</p> + +<ul> + <li>Add an attribute to make browsers display some default controls.</li> + <li>Add some appropriate fallback text for browsers that don't support <code><video></code>.</li> + <li>Add multiple sources, containing the paths to the video files. The files are called <code>video.mp4</code> and <code>video.webm</code>, and are in a folder inside the current folder called <code>media</code>.</li> + <li>Let the browser know in advance what video formats the sources point to, so it can make an informed choice of which one to download ahead of time.</li> + <li>Give the <code><video></code> a width and height equal to its intrinsic size (320 by 240 pixels).</li> + <li>Make the video muted by default.</li> + <li>Display the text tracks contained in the <code>media</code> folder, in a file called <code>subtitles_en.vtt</code>, when the video is playing. You must explicitly set the type as subtitles, and the subtitle language to English.</li> +</ul> + +<p>Try updating the live code below to recreate the finished example:</p> + +<p>{{EmbedGHLiveSample("learning-area/html/multimedia-and-embedding/tasks/media-embed/mediaembed2.html", '100%', 700)}}</p> + +<div class="blockIndicator note"> +<p><a href="https://github.com/mdn/learning-area/tree/master/html/multimedia-and-embedding/tasks/media-embed/mediaembed2-download.html">Download the starting point for this task</a> to work in your own editor or in an online editor.</p> +</div> + +<h2 id="Multimedia_and_embedding_3">Multimedia and embedding 3</h2> + +<p>For this final task you have two tasks to do:</p> + +<ul> + <li>Embed a PDF into the page. The PDF is called <code>mypdf.pdf</code>, and is contained in the <code>media</code> folder.</li> + <li>Go to a sharing site like YouTube or Google Maps, and embed a video or other media item into the page.</li> +</ul> + +<p>Try updating the live code below to recreate the finished example:</p> + +<p>{{EmbedGHLiveSample("learning-area/html/multimedia-and-embedding/tasks/media-embed/mediaembed3.html", '100%', 700)}}</p> + +<div class="blockIndicator note"> +<p><a href="https://github.com/mdn/learning-area/tree/master/html/multimedia-and-embedding/tasks/media-embed/mediaembed3-download.html">Download the starting point for this task</a> to work in your own editor or in an online editor.</p> +</div> + +<h2 id="Assessment_or_further_help">Assessment or further help</h2> + +<p>You can practice these examples in the Interactive Editors above.</p> + +<p>If you would like your work assessed, or are stuck and want to ask for help:</p> + +<ol> + <li>Put your work into an online shareable editor such as <a href="https://codepen.io/">CodePen</a>, <a href="https://jsfiddle.net/">jsFiddle</a>, or <a href="https://glitch.com/">Glitch</a>. You can write the code yourself, or use the starting point files linked to in the above sections.</li> + <li>Write a post asking for assessment and/or help at the <a class="external external-icon" href="https://discourse.mozilla.org/c/mdn/learn" rel="noopener">MDN Discourse forum Learning category</a>. Your post should include: + <ul> + <li>A descriptive title such as "Assessment wanted for HTML image basics 1 skill test".</li> + <li>Details of what you have already tried, and what you would like us to do, e.g. if you are stuck and need help, or want an assessment.</li> + <li>A link to the example you want assessed or need help with, in an online shareable editor (as mentioned in step 1 above). This is a good practice to get into — it's very hard to help someone with a coding problem if you can't see their code.</li> + <li>A link to the actual task or assessment page, so we can find the question you want help with.</li> + </ul> + </li> +</ol> diff --git a/files/zh-cn/learn/html/multimedia_and_embedding/其他嵌入技术/index.html b/files/zh-cn/learn/html/multimedia_and_embedding/其他嵌入技术/index.html new file mode 100644 index 0000000000..c66ca6499e --- /dev/null +++ b/files/zh-cn/learn/html/multimedia_and_embedding/其他嵌入技术/index.html @@ -0,0 +1,254 @@ +--- +title: 从对象到iframe - 其他嵌入技术 +slug: Learn/HTML/Multimedia_and_embedding/其他嵌入技术 +translation_of: Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/HTML/Multimedia_and_embedding/Video_and_audio_content", "Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web", "Learn/HTML/Multimedia_and_embedding")}}</div> + +<p class="summary"><font>到目前为止,您应该掌握了将图像、视频和音频嵌入到网页上的诀窍了。此刻,让我们继续深入学习,来看一些能让您在网页中嵌入各种内容类型的元素:</font> {{htmlelement("iframe")}}, {{htmlelement("embed")}} 和{{htmlelement("object")}} 元素。<code><iframe></code><font><font>用</font></font>于嵌入其他网页,另外两个元素则允许您嵌入PDF,SVG,甚至Flash — 一种正在被淘汰的技术,但您仍然会时不时的看到它。</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">预备知识:</th> + <td><font><font>基</font></font>本的计算机知识,<a href="/zh-CN/Learn/Getting_started_with_the_web/Installing_basic_software">安装基础软件</a>,<a href="/zh-CN/Learn/Getting_started_with_the_web/Dealing_with_files">文件处理</a> 的基本知识,熟悉HTML基础知识(阅读 <a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Getting_started">开始学习 HTML</a>)以及本模块中以前的文章<font><font>。</font></font></td> + </tr> + <tr> + <th scope="row">学习目标:</th> + <td><font><font>要了解如何使用<code><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/object" title="HTML <object>元素表示外部资源,可以将其视为图像,嵌套浏览上下文或要由插件处理的资源。"><object></a><font face="Open Sans, arial, x-locale-body, sans-serif"><span style="background-color: #ffe8d4;">、</span></font></code></font></font><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/embed" title="HTML <embed>元素表示外部应用程序或交互式内容(换句话说,插件)的集成点。"><code><embed></code></a><font><font>以及</font></font><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe" title="HTML <iframe>元素表示嵌套的浏览上下文,有效地将另一个HTML页面嵌入到当前页面中。 在HTML 4.01中,文档可能包含一个头部和一个主体或头部和框架集,但不包括主体和框架集。 但是,一个<iframe>可以在普通文档正文中使用。 每个浏览上下文都有自己的会话历史和活动文档。 包含嵌入内容的浏览上下文称为父浏览上下文。 顶级浏览上下文(没有父级)通常是浏览器窗口。"><code><iframe></code></a><font><font>在网页中嵌入部件,例如</font></font><font><font>Flash电影或其他网页。</font></font></td> + </tr> + </tbody> +</table> + +<h2 id="嵌入的简史"><font><font>嵌入的简史</font></font></h2> + +<p><font><font>很久以前,很流行在网络上使用</font></font><strong><font><font>框架</font></font></strong><font><font>创建网站 — 网站的一小部分存储于单独的HTML页面中</font><font>。</font><font>这些被嵌入在一个称为</font></font><strong><font><font>框架集</font></font></strong><font><font>的主文档中</font><font>,它允许您指定每个框架能够填充在屏幕上的区域,非常像调整表格的列和行的大小。</font><font>这些做法在90年代中期至90年代后期被认为是比较酷的,有证据表明,将网页分解成较小的块,这样有利于下载速度 —</font></font>尤其是在那时网络连接速度太慢的情况下更为明显<font><font>。</font><font>然而,这些技术有很多问题,随着网络速度越来越快,这些技术带来的问题远超过它们带来的积极因素,所以你再也看不到它们被使用了。</font></font></p> + +<p><font><font>一小段时间之后(20世纪90年代末,21世纪初),插件技术变得非常受欢迎,例如</font></font><a href="https://developer.mozilla.org/en-US/docs/Glossary/Java"><font><font>Java Applet</font></font></a><font><font>和</font></font><a href="https://developer.mozilla.org/en-US/docs/Glossary/Adobe_Flash"><font><font>Flash</font></font></a><font><font> — 这些技术允许网络开发者将丰富的内容嵌入到网页中,例如视频和动画等,这些内容不能通过HTML单独实现。</font><font>嵌入这些技术是通过诸如</font></font><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/object" title="HTML <object>元素表示外部资源,可以将其视为图像,嵌套浏览上下文或要由插件处理的资源。"><code><object></code></a><font><font>和较少使用</font></font><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/embed" title="HTML <cke:embed></cke:embed>元素表示外部应用程序或交互式内容(换句话说,插件)的集成点。"><code><embed></code></a><font><font>的</font><font>元素来实现的</font><font>,当时</font></font><font><font>它们非常有用。</font><font>由于许多问题,包括可访问性、安全性、文件大小等,它们已经过时了; </font><font>如今,大多数移动设备不再支持这些插件,桌面端也逐渐不再支持。</font></font></p> + +<p><font><font>最后,</font></font><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe" title="HTML <iframe>元素表示嵌套的浏览上下文,有效地将另一个HTML页面嵌入到当前页面中。 在HTML 4.01中,文档可能包含一个头部和一个主体或头部和框架集,但不包括主体和框架集。 但是,一个<iframe>可以在普通文档正文中使用。 每个浏览上下文都有自己的会话历史和活动文档。 包含嵌入内容的浏览上下文称为父浏览上下文。 顶级浏览上下文(没有父级)通常是浏览器窗口。"><code><iframe></code></a><font><font>元素出现了(连同其他嵌入内容的方式,如</font></font><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas" title="使用HTML <canvas>元素与canvas脚本API来绘制图形和动画。"><code><canvas></code></a><font><font>,</font></font><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video" title="使用HTML <video>元素将视频内容嵌入到文档中。"><code><video></code></a><font><font>等),它提供了一种将整个web页嵌入到另一个网页的方法,看起来就像那个web页是另一个网页的一个</font></font>{{htmlelement("img")}}或其他元素一样。{{htmlelement("iframe")}}现在经常被使用<font><font>。</font></font></p> + +<p><font><font>了解完历史之后,让我们继续往下看以了解如何使用它们。</font></font></p> + +<h2 id="自主学习:嵌入类型的使用"><font><font>自主学习:嵌入类型的使用</font></font></h2> + +<p><font><font>在这篇文章中,我们将直接进入自主学习部分,让你立即体会到嵌入技术的实用性。大家都非常熟悉</font></font><a href="https://www.youtube.com/"><font><font>Youtube</font></font></a><font><font>,但很多人不了解它所提供的一些分享功能。让我们来看看Youtube如何让我们通过</font></font><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe" title="HTML <iframe>元素表示嵌套的浏览上下文,有效地将另一个HTML页面嵌入到当前页面中。 在HTML 4.01中,文档可能包含一个头部和一个主体或头部和框架集,但不包括主体和框架集。 但是,一个<iframe>可以在普通文档正文中使用。 每个浏览上下文都有自己的会话历史和活动文档。 包含嵌入内容的浏览上下文称为父浏览上下文。 顶级浏览上下文(没有父级)通常是浏览器窗口。"><code><iframe></code></a><font><font>在页面中嵌入喜欢的视频</font></font><font><font>。</font></font></p> + +<ol> + <li><font><font>首先,去Youtube找一个喜欢的视频。</font></font></li> + <li><font><font>在视频下方,您会看到一个</font></font><em><font><font>共享</font></font></em><font><font>按钮 - 点击查看共享选项。</font></font></li> + <li><font><font>选择“ </font></font><em><font><font>嵌入”</font></font></em><font><font>选项卡,您将得到一些</font></font><code><iframe></code><font><font>代码 - 复制一下。</font></font></li> + <li><font><font>粘贴到</font><font>下面</font><font>的</font></font><em><font><font>输入</font></font></em><font><font>框里,看看</font></font><em><font><font>输出</font></font></em><font><font>结果是什么</font><font>。</font></font></li> +</ol> + +<p><font><font>此外,您还可以试试</font><font>在示例中</font><font>嵌入</font></font><a href="https://www.google.com/maps/"><font><font>Google地图</font></font></a><font><font>:</font></font></p> + +<ol> + <li><font><font>去Google地图找一个喜欢的地图。</font></font></li> + <li><font><font>点击UI左上角的“汉堡菜单”(三条水平线)。</font></font></li> + <li><font><font>选择</font></font><em><font><font>共享或嵌入地图</font></font></em><font><font>选项。</font></font></li> + <li><font><font>选择嵌入地图选项,这将给你一些</font></font><code><iframe></code><font><font>代码 - 复制一下。</font></font></li> + <li><font><font>粘贴到下面</font><font>的</font></font><em><font><font>输入</font></font></em><font><font>框,看看</font></font><em><font><font>输出</font></font></em><font><font>结果是什么</font><font>。</font></font></li> +</ol> + +<p>如果你犯了某些错误,你可以点击<em>Reset按钮以重置编辑器。</em>如果你确实被卡住了, 按下Show <em>solution按钮以借鉴答案。</em></p> + +<div class="hidden"> +<h6 id="Playable_code">Playable code</h6> + +<pre class="brush: html notranslate"><!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <style> body { font-family: '微软雅黑', Helvetica, Arial, sans-serif; margin: 10px; background: #f5f9fa; } h2 { font-size: 16px; } code, textarea { font-family: Consolas, Menlo, monospace; } .output { min-height: 200px; } .input { min-height: 100px; width: 95%; } .a11y-label { margin: 0; text-align: right; font-size: 0.7rem; width: 98%; } .controls { width: 96%; text-align: right; } </style> </head> <body> <h2>实时输出</h2> <div class="output"></div> <h2>可编辑代码</h2> <p class="a11y-label">按 ESC 退出编辑区域,按 Tab 可插入制表符 <code>'\t'</code> </p> <textarea id="code" class="input"></textarea> <div class="controls"> <button id="btn-reset">重置</button> <button id="btn-solution">显示答案</button> </div> <script> const btnReset = document.getElementById('btn-reset'); const btnSolution = document.getElementById('btn-solution'); const blockOutput = document.querySelector('.output'); const blockInput = document.querySelector('.input'); const original = '<p>改革春风吹满地</p>'; const answer = `<iframe src="https://player.bilibili.com/player.html?aid=19390801&cid=31621681&page=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"> </iframe> <p>改革春风吹满地</p>`; let userEntry = ""; init(); btnReset.addEventListener('click', init); btnSolution.addEventListener('click', () => { if (btnSolution.textContent === '显示答案') { blockInput.value = blockOutput.innerHTML = answer; btnSolution.textContent = '隐藏答案'; } else { blockInput.value = blockOutput.innerHTML = userEntry; btnSolution.textContent = '显示答案'; } }); blockInput.addEventListener('keydown', (e) => { switch (e.key) { case 'Tab': e.preventDefault(); insertAtCursor('\t'); break; case "Escape": blockInput.blur(); break; } }); blockInput.addEventListener('keyup', () => { userEntry = blockInput.value; blockOutput.innerHTML = blockInput.value; if (btnSolution.textContent === '隐藏答案') { btnSolution.textContent = '显示答案'; } }); function init() { userEntry = blockOutput.innerHTML = blockInput.value = original; btnSolution.textContent = '显示答案'; } function insertAtCursor(text) { const scrollPos = blockInput.scrollTop; const cursorPos = blockInput.selectionStart; const front = blockInput.value.substring(0, cursorPos); const back = blockInput.value.substring( blockInput.selectionEnd, blockInput.value.length); blockInput.value = front + text + back; blockInput.selectionStart = blockInput.selectionEnd = cursorPos + text.length; blockInput.focus(); blockInput.scrollTop = scrollPos; } </script> </body> </html></pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code', 700, 600, "", "", "hide-codepen-jsfiddle") }}</p> + +<h2 id="Iframe详解"><font><font>Iframe详解</font></font></h2> + +<p><font><font>是不是很简单又有趣呢?</font></font><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe" title="HTML <iframe>元素表示嵌套的浏览上下文,有效地将另一个HTML页面嵌入到当前页面中。 在HTML 4.01中,文档可能包含一个头部和一个主体或头部和框架集,但不包括主体和框架集。 但是,一个<iframe>可以在普通文档正文中使用。 每个浏览上下文都有自己的会话历史和活动文档。 包含嵌入内容的浏览上下文称为父浏览上下文。 顶级浏览上下文(没有父级)通常是浏览器窗口。"><code><iframe></code></a><font><font>元素旨在允许您将其他Web文档嵌入到当前文档中。</font><font>这很适合将第三方内容嵌入您的网站,您可能无法直接控制,也不希望实现自己的版本 - 例如来自在线视频提供商的视频,</font></font><a href="https://disqus.com/"><font><font>Disqus</font></font></a><font><font>等评论系统</font><font>,在线地图提供商,广告横幅等。您通过本课程使用的实时可编辑示例就是使用</font></font><code><iframe></code><font><font> </font><font>实现的</font><font>。</font></font></p> + +<p><font><font>我</font></font><font><font>们会在后面提到,关于</font></font><code><iframe></code><font><font>有一些严重的</font></font>{{anch("安全隐患")}}<font><font>需要考虑</font></font><font><font>,但这并不意味着你不应该在你的网站上使用它们 — 它只需要一些知识和仔细地思考。让我们更详细地探索这些代码。假设您想在其中一个网页上加入MDN词汇表,您可以尝试以下方式:</font></font></p> + +<pre class="notranslate"><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> +</pre> + +<p><font><font>此示例包括使用以下所需的</font></font><code><iframe></code><font><font>基本要素:</font></font></p> + +<dl> + <dt><code><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-allowfullscreen">allowfullscreen</a></code></dt> + <dd><font><font>如果设置,</font></font><code><iframe></code><font><font>则可以通过</font></font><a href="/zh-CN/docs/Web/API/Fullscreen_API"><font><font>全屏API</font></font></a><font><font>设置为全屏模式</font><font>(稍微超出本文的范围)。</font></font></dd> + <dt><code><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-frameborder">frameborder</a></code></dt> + <dd><font><font>如果设置为1,则会告诉浏览器在此框架和其他框架之间绘制边框,这是默认行为。</font><font>0删除边框。不推荐这样设置</font><font>,因为</font><font>在</font><a href="https://developer.mozilla.org/en-US/docs/Glossary/CSS" title="CSS:CSS(Cascading Style Sheets)是一种声明式语言,用于控制浏览器中网页的外观。"><font>CSS中</font></a><font>可以更好地实现相同的效果</font><font>。</font></font><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/border" title="边框CSS属性是用于一次设置所有单个边框属性值的缩写属性:border-width,border-style和border-color。 与所有速记属性一样,未指定的任何单个值都将设置为其对应的初始值。 重要的是,边框不能用于指定border-image的自定义值,而是将其设置为其初始值,即none。"><code>border</code></a><code>: none;</code></dd> + <dt><code><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-src">src</a></code></dt> + <dd><font><font>该属性与</font></font><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video" title="使用HTML <video>元素将视频内容嵌入到文档中。"><code><video></code></a><font><font>/</font></font><code><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img" title="HTML <img>元素表示文档中的图像。"><img></a></code><font><font>一样包</font></font><font><font>含指向要嵌入文档的URL路径。</font></font></dd> + <dt><code><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-width">width</a></code><font><font> 和 </font></font><code><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-height">height</a></code></dt> + <dd><font><font>这些属性指定您想要的iframe的宽度和高度。</font></font></dd> +</dl> + +<dl> + <dt>备选内容</dt> + <dd><font><font>与</font></font><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video" title="使用HTML <video>元素将视频内容嵌入到文档中。"><code><video></code></a><font><font>等其</font></font><font><font>他类似元素相同</font></font><font><font>,您可以在</font></font><code><iframe></iframe></code><font><font>标签</font><font>之间包含备选内容,</font><font>如果浏览器不支持</font></font><code><iframe></code><font><font>,将会显示备选内容,</font></font><font><font>这种情况下,我们已经添加了一个到该页面的链接。现在</font><font>您几乎不可能遇到任何不支持</font></font><code><iframe></code><font><font>的</font><font>浏览器</font><font>。</font></font></dd> + <dt><code><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-sandbox">sandbox</a></code></dt> + <dd><font><font>该属性需要在已经支持其他</font></font><code><iframe></code><font><font>功能(例如IE 10及更高版本)但</font><font>稍微更现代的浏览器上才能工作,该属性可以</font><font>提高安全性设置; </font><font>我们将在下一节中更加详细地谈到。</font></font></dd> +</dl> + +<div class="note"> +<p><strong><font><font>注意</font></font></strong><font><font>:为了提高速度,</font></font><font><font>在主内容完成加载后</font><font>,使用JavaScript设置iframe的</font><font><code>src</code>属性</font><font>是个好主意</font><font>。</font><font>这使您的页面可以更快地被使用,并减少您的官方页面加载时间(重要的</font></font><a href="https://developer.mozilla.org/en-US/docs/Glossary/SEO" title="SEO:SEO(搜索引擎优化)是使网站在搜索结果中更加可见的过程,也称为提高搜索排名。"><font><font>SEO</font></font></a><font><font>指标)。</font></font></p> +</div> + +<h3 id="安全隐患"><font><font>安全隐患</font></font></h3> + +<p><font><font>以上我们提到了安全问题 - 现在我们来详细介绍一下这一点。</font><font>我们并不期望您第一次就能完全理解所有内容; 我们只想让您意识到这一问题,在您更有经验并开始考虑在您的实验和工作中</font><font>使用</font></font><code><iframe></code><font><font>时为你提供参考</font><font>。</font><font>此外,没有必要害怕和不使用</font></font><code><iframe></code><font><font>—你只需要谨慎一点。继续看下去吧</font><font>...</font></font></p> + +<p><font><font>浏览器制造商和Web开发人员了解到</font><font>网络上的坏人(通常被称为</font><strong><font>黑客</font></strong><font>,或更准确地说是</font><strong><font>破解者</font></strong><font>)</font><font>,如果他们试图恶意修改您的网页或欺骗人们进行不想做的事情时常把iframe作为共同的攻击目标(官方术语:</font></font><strong><font><font>攻击向量</font></font></strong><font><font>),例如显示用户名和密码等敏感信息。因此,规范工程师和浏览器开发人员已经开发了各种安全机制,使</font></font><code><iframe></code><font><font>更加安全,这有些最佳方案值得我们考虑 - 我们将在下面介绍其中的一些。</font></font></p> + +<div class="note"> +<p><a href="https://en.wikipedia.org/wiki/Clickjacking" title="点击劫持"><font><font>单击劫持</font></font></a><font><font>是一种常见的iframe攻击,黑客将隐藏的iframe嵌入到您的文档中(或将您的文档嵌入到他们自己的恶意网站),并使用它来捕获用户的交互。</font><font>这是误导用户或窃取敏感数据的常见方式。</font></font></p> +</div> + +<p><font><font>一个快速的例子 — 尝试在浏览器中加载上面的例子 - 你也可以</font></font><a href="http://mdn.github.io/learning-area/html/multimedia-and-embedding/other-embedding-technologies/iframe-detail.html"><font><font>在Github上找到它</font></font></a><font><font>(</font></font><a href="https://github.com/mdn/learning-area/blob/gh-pages/html/multimedia-and-embedding/other-embedding-technologies/iframe-detail.html"><font><font>参见源代码</font></font></a><font><font>)。你将不会看到任何内容,但如果你点击</font></font><font><font><a href="https://developer.mozilla.org/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools">浏览器开发者工具</a>中的<em>控制台</em></font></font><font><font>,你会看到一条消息,告诉你为什么没有显示内容。</font><font>在Firefox中,您会</font></font><em><font><font>被告知:“X-Frame-Options拒绝加载https://developer.mozilla.org/en-US/docs/Glossary”</font></font></em><font><font>。</font><font>这是因为构建MDN的开发人员已经在网站页面的服务器上设置了一个不允许被嵌入到</font></font><code><iframe></code><font><font>的设置(请参阅</font></font><a href="https://developer.mozilla.org/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies#配置CSP指令"><font><font>配置CSP指令</font></font></a><font><font>)这是有必要的 — 整个MDN页面被嵌入在其他页面中没有多大意义,除非您想要将其嵌入到您的网站上并将其声称为自己的内容,或尝试通过单击劫持来窃取数据,这都是非常糟糕的事情。</font><font>此外,如果每个人都这样做,所有额外的带宽将花费Mozilla很多资金。</font></font></p> + +<h4 id="只有在必要时嵌入"><font><font>只有在必要时嵌入</font></font></h4> + +<p><font><font>有时嵌入第三方内容(例如YouTube视频和地图)是有意义的,但如果您只在完全需要时嵌入第三方内容,您可以省去很多麻烦。</font><font>网络安全的一个很好的经验法则是</font></font><em><font><font>“你怎么谨慎都不为过,如果你决定要做这件事,多检查一遍;如果是别人做的,在被证明是安全的之前,都假设这是危险的。”</font></font></em></p> + +<div> +<p>除了安全问题,你还应该意识到知识产权问题。无论在线内容还是离线内容,绝大部分内容都是有版权的,甚至是一些你没想到有版权的内容(例如,<a href="https://commons.wikimedia.org/wiki/Main_Page">Wikimedia Commons</a>上的大多数图片)。不要在网页上展示一些不属于你的内容,除非你是所有者或所有者给了你明确的、书面的许可。对于侵犯版权的惩罚是严厉的。再说一次,你再小心也不为过。</p> + +<p>如果内容获得许可,你必须遵守许可条款。例如,MDN上的内容是<a href="/zh-CN/docs/MDN/About#%E7%89%88%E6%9D%83%E5%92%8C%E8%AE%B8%E5%8F%AF">在CC-BY-SA下许可的</a>,这意味着,如果你要引用我们的内容,就必须<a href="https://wiki.creativecommons.org/wiki/Best_practices_for_attribution">用适当的方式注明来源</a>,即使你对内容做了实质性的修改。</p> +</div> + +<h4 id="使用_HTTPS">使用 HTTPS</h4> + +<p><a href="https://developer.mozilla.org/en-US/docs/Glossary/HTTPS" title="HTTPS:HTTPS(HTTP Secure)是HTTP协议的加密版本。 它通常使用SSL或TLS来加密客户端和服务器之间的所有通信。 这种安全连接允许客户端安全地与服务器交换敏感数据,例如用于银行活动或在线购物。"><font><font>HTTPS</font></font></a><font><font>是</font></font><a href="https://developer.mozilla.org/en-US/docs/Glossary/HTTP" title="HTTP:HTTP(超文本传输协议)是启用Web上文件传输的基本协议。 HTTP是文本的(所有的通信都是以纯文本形式进行的)和无状态的(没有通信知道以前的通信)。"><font><font>HTTP</font></font></a><font><font>的加密版本</font><font>。</font><font>您应该尽可能使用HTTPS为您的网站提供服务:</font></font></p> + +<ol> + <li><font><font>HTTPS减少了远程内容在传输过程中被篡改的机会,</font></font></li> + <li><font><font>HTTPS防止嵌入式内容访问您的父文档中的内容,反之亦然。</font></font></li> +</ol> + +<p><font><font>使用HTTPS需要一个安全证书,这可能是昂贵的(尽管</font></font><a href="https://letsencrypt.org/">Let's Encrypt</a>让这件<font><font>事变得更容易),如果你没有,可以使用HTTP来为你的父文档提供服务。</font><font>但是,由于HTTPS的第二个好处,</font></font><em><font><font>无论成本如何,您绝对不能使用HTTP嵌入第三方内容</font></font></em><font><font>(在最好的情况下,您的用户的Web浏览器会给他们一个可怕的警告)。所有有声望的公司,例如Google Maps或Youtube,当您嵌入内容时,</font></font><code><iframe></code><font><font>将通过HTTPS提供 - 查看</font></font><code><iframe></code> <code>src</code><font><font>属性内的URL。</font></font></p> + +<div class="note"> +<p><strong><font><font>注意</font></font></strong><font><font>:</font></font><a href="https://developer.mozilla.org/en-US/docs/Learn/Common_questions/Using_Github_pages"><font><font>Github页面</font></font></a><font><font>允许默认情况下通过HTTPS提供内容,因此对托管内容很有用。</font><font>如果您正在使用不同的托管,并且不确定,请向您的托管服务商询问。</font></font></p> +</div> + +<h4 id="始终使用sandbox属性"><font><font>始终使用</font></font><code>sandbox</code><font><font>属性</font></font></h4> + +<p>想尽可能减少攻击者在你的网站上做坏事的机会,那么你应该给嵌入的内容仅能完成自己工作的权限<em><font><font>。</font></font></em><font><font>当然,这也适用于你自己的内容。一个允许包含在其里的代码以适当的方式执行或者用于测试</font><font>,但不能对其他代码库(意外或恶意)造成任何损害的容器称为</font></font><a href="https://en.wikipedia.org/wiki/Sandbox_(computer_security)"><font><font>沙盒</font></font></a><font><font>。</font></font></p> + +<p><font><font>未沙盒化(Unsandboxed)内容可以做得太多(执行JavaScript,提交表单,弹出窗口等)默认情况下,您应该使用没有参数的<code>sandbox</code></font><font>属性</font><font>来强制执行所有可用的限制</font><font>,如我们前面的示例所示。</font></font></p> + +<p><font><font>如果绝对需要,您可以逐个添加权限(</font></font><code>sandbox=""</code><font><font>属性值内) - 请参阅</font></font><code><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-sandbox">sandbox</a></code><font><font>所有可用选项</font><font>的</font><font>参考条目。</font><font>其中重要的一点是,你</font></font><em><font><font>永远不</font></font></em><font><font>应该</font></font><font><font>同时添加</font></font><code>allow-scripts</code><font><font>和</font></font><code>allow-same-origin</code><font><font>到你的</font></font><code>sandbox</code><font><font>属性中-</font></font>在这种情况下,嵌入式内容可以绕过阻止站点执行脚本的同源安全策略,并使用JavaScript完全关闭沙盒。</p> + +<div class="note"> +<p><strong><font><font>注意</font></font></strong><font><font>:</font></font>如果攻击者可以欺骗人们直接访问恶意内容(在iframe之外),则沙盒无法提供保护。如果某些内容可能是恶意的(例如,用户生成的内容),请保证其是从不同的<a href="https://developer.mozilla.org/en-US/docs/Glossary/domain">域</a>向您的主站点提供的。</p> +</div> + +<h4 id="配置CSP指令"><font><font>配置CSP指令</font></font></h4> + +<p><a href="https://developer.mozilla.org/en-US/docs/Glossary/CSP" title="CSP:CSP(内容安全策略)用于检测和减轻某些类型的网站相关攻击,如XSS和数据注入。"><font><font>CSP</font></font></a><font><font>代表</font></font><strong><a href="https://developer.mozilla.org/en-US/docs/Web/Security/CSP"><font><font>内容安全策略</font></font></a></strong><font><font>,它提供</font></font><a href="https://developer.mozilla.org/en-US/docs/Web/Security/CSP/CSP_policy_directives"><font><font>一组HTTP标头</font></font></a><font><font>(由web服务器发送时与元数据一起发送的元数据),旨在提高HTML文档的安全性。</font><font>在</font></font><code><iframe></code>s<font><font>安全性方面</font></font><font><font>,您可以</font></font><em><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/X-Frame-Options"><font><font>将服务器配置为发送适当的</font></font><code>X-Frame-Options</code><font><font> 标题。</font></font></a></em><font><font>这样做可以防止其他网站在其网页中嵌入您的内容(这将导致</font></font><a href="https://en.wikipedia.org/wiki/clickjacking" title="点击劫持"><font><font>点击</font></font></a><font><font>和一系列其他攻击),正如我们之前看到的那样,MDN开发人员已经做了这些工作。</font></font></p> + +<div class="note"> +<p><strong><font><font>注意</font></font></strong><font><font>:您可以阅读Frederik Braun的帖子</font></font><font><font><a href="https://blog.mozilla.org/security/2013/12/12/on-the-x-frame-options-security-header/">在X-Frame-Options安全性头上</a>来</font></font><font><font>获取有关此主题的更多背景信息。</font><font>显然,在这篇文章中已经解释得很清楚了。</font></font></p> +</div> + +<h2 id="<embed>和<object>元素"><font><font><embed>和<object>元素</font></font></h2> + +<p><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/embed" title="HTML <embed>元素表示外部应用程序或交互式内容(换句话说,插件)的集成点。"><code><embed></code></a><font><font>和</font></font><code><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/object" title="HTML <object>元素表示外部资源,可以将其视为图像,嵌套浏览上下文或要由插件处理的资源。"><object></a></code><font><font>元素</font></font><font><font>的功能不同于</font></font><code><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe" title="HTML <iframe>元素表示嵌套的浏览上下文,有效地将另一个HTML页面嵌入到当前页面中。 在HTML 4.01中,文档可能包含一个头部和一个主体或头部和框架集,但不包括主体和框架集。 但是,一个<iframe>可以在普通文档正文中使用。 每个浏览上下文都有自己的会话历史和活动文档。 包含嵌入内容的浏览上下文称为父浏览上下文。 顶级浏览上下文(没有父级)通常是浏览器窗口。"><iframe></a></code>—— 这<font><font>些元素是用来嵌入多种类型的外部内容的通用嵌入工具,其中包括像Java小程序和Flash,PDF(可在浏览器中显示为一个PDF插件)这样的插件技术,甚至像视频,SVG和图像的内容!</font></font></p> + +<div class="note"> +<p><strong><font><font>注意</font></font></strong><font><font>:</font></font><strong><font><font>插件</font></font></strong><font><font>是一种对浏览器原生无法读取的内容提供访问权限的软件。</font></font></p> +</div> + +<p><font><font>然而,您不太可能使用这些元素 - Applet几年来一直没有被使用;由于许多原因,Flash不再受欢迎(见</font><font>下面的</font></font><a href="https://developer.mozilla.org/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies#The_case_against_plugins"><font><font>插件案例</font></font></a><font><font>);PDF更倾向于被链接而不是被嵌入;其他内容,如图像和视频都有更优秀、更容易元素来处理。插件和这些嵌入方法真的是一种传统技术,我们提及它们主要是为了以防您在某些情况下遇到问题,比如内部网或企业项目等。</font></font></p> + +<p><font><font>如果您发现自己需要嵌入插件内容,那么您至少需要一些这样的信息:</font></font></p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col"></th> + <th scope="col">{{htmlelement("embed")}}</th> + <th scope="col">{{htmlelement("object")}}</th> + </tr> + </thead> + <tbody> + <tr> + <td><font>嵌入内容的</font><a href="https://developer.mozilla.org/en-US/docs/Glossary/URL" title="URL: Uniform Resource Locator (URL) is a text string specifying where a resource can be found on the Internet."><font>网址</font></a></td> + <td>{{htmlattrxref('src','embed')}}</td> + <td>{{htmlattrxref('data','object')}}</td> + </tr> + <tr> + <td><font><font>嵌入内容的</font></font><em><font><font>准确</font></font></em><a href="https://developer.mozilla.org/en-US/docs/Glossary/MIME_type" title="媒体类型:MIME类型(现在称为“媒体类型”,有时也称为“内容类型”)是与指示文件类型的文件一起发送的字符串(例如,声音文件可能标记为音频/ ogg,或一个图像文件图像/ png)。 它的作用与传统上在Windows上的文件扩展名相同。"><font><font>媒体类型</font></font></a></td> + <td>{{htmlattrxref('type','embed')}}</td> + <td>{{htmlattrxref('type','object')}}</td> + </tr> + <tr> + <td><font><font>由插件控制的框的高度和宽度(以CSS像素为单位)</font></font></td> + <td>{{htmlattrxref('height','embed')}}<br> + {{htmlattrxref('width','embed')}}</td> + <td>{{htmlattrxref('height','object')}}<br> + {{htmlattrxref('width','object')}}</td> + </tr> + <tr> + <td>名称和值,将插件作为参数提供</td> + <td>具有这些名称和值的ad hoc属性</td> + <td><font><font>单标签</font></font><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/param" title="HTML <param>元素定义了一个<object>元素的参数。"><code><param></code></a><font><font>元素,包含在内</font></font><code><object></code></td> + </tr> + <tr> + <td>独立的HTML内容作为不可用资源的回退</td> + <td><font><font>不支持(</font></font><code><noembed></code><font><font>已过时)</font></font></td> + <td><font><font>包含在</font><font>元素</font></font><code><object></code><font><font>之后</font></font><code><param></code></td> + </tr> + </tbody> +</table> + +<div class="note"> +<p><strong><font><font>注意</font></font></strong><font><font>:</font></font><code><object></code><font><font>需要</font></font><code>data</code><font><font>属性,</font></font><code>type</code><font><font>属性或两者。</font><font>如果您同时使用这两个,您也可以使用该</font></font><code><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/object#attr-typemustmatch">typemustmatch</a></code><font><font>属性(仅在Firefox中实现,在本文中)。</font></font><code>typemustmatch</code><font><font>保持嵌入文件不运行,除非</font></font><code>type</code><font><font>属性提供正确的媒体类型。</font></font><code>typemustmatch</code><font><font>因此,当您嵌入来自不同</font></font><a href="https://developer.mozilla.org/en-US/docs/Glossary/origin" title="来源:Web内容的起源由方案(协议),主机(域)和用于访问它的URL的端口定义。 只有当方案,主机和端口都匹配时,两个对象具有相同的原点。"><font><font>来源的</font></font></a><font><font>内容</font><font>(可以防止攻击者通过插件运行任意脚本)</font><font>时,可以赋予重要的安全优势</font><font>。</font></font></p> +</div> + +<p><font><font>下面是一个使用该</font></font><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/embed" title="HTML <embed>元素表示外部应用程序或交互式内容(换句话说,插件)的集成点。"><code><embed></code></a><font><font>元素嵌入Flash影片</font><font>的示例</font><font>(请参阅</font><font>此处的</font></font><a href="http://mdn.github.io/learning-area/html/multimedia-and-embedding/other-embedding-technologies/embed-flash.html"><font><font>Github</font></font></a><font><font>,并</font></font><a href="https://github.com/mdn/learning-area/blob/gh-pages/html/multimedia-and-embedding/other-embedding-technologies/embed-flash.html"><font><font>检查源代码</font></font></a><font><font>):</font></font></p> + +<pre class="brush: html notranslate"><embed src="whoosh.swf" quality="medium" + bgcolor="#ffffff" width="550" height="400" + name="whoosh" align="middle" allowScriptAccess="sameDomain" + allowFullScreen="false" type="application/x-shockwave-flash" + pluginspage="http://www.macromedia.com/go/getflashplayer"></pre> + +<p><font><font>很可怕,不是吗 。</font><font>Adobe Flash工具生成的HTML往往更糟糕,使用</font><font>嵌入</font></font><code><object></code><font><font>元素的</font></font><code><embed></code><font><font>元素来覆盖所有的基础(查看一个例子)。甚至有一段时间,Flash被成功地用作HTML5视频的备用内容,但是这种情况越来越被认为是不必要的。</font></font></p> + +<p><font><font>现在来看一个</font></font><code><object></code><font><font>将PDF嵌入一个页面的例子</font></font><font><font>(参见</font><a href="http://mdn.github.io/learning-area/html/multimedia-and-embedding/other-embedding-technologies/object-pdf.html"><font>实例</font></a><font>和</font></font><a href="https://github.com/mdn/learning-area/blob/gh-pages/html/multimedia-and-embedding/other-embedding-technologies/object-pdf.html"><font><font>源代码</font></font></a><font><font>):</font></font></p> + +<pre class="brush: html notranslate"><object data="mypdf.pdf" type="application/pdf" + width="800" height="1200" typemustmatch> + <p>You don't have a PDF plugin, but you can <a href="myfile.pdf">download the PDF file.</a></p> +</object></pre> + +<p><font><font>PDF是纸与数据之间重要的阶梯,但它们</font></font><a href="http://webaim.org/techniques/acrobat/acrobat">在可访问性上有些问题</a><font><a href="http://webaim.org/techniques/acrobat/acrobat"><font>,</font></a><font>并且可能难以在小屏幕上阅读。它们在一些圈子中仍然受欢迎,我们最好是用链接指向它们,而不是将其嵌入到网页中,以便它们可以在单独的页面上被下载或被阅读。</font></font></p> + +<h3 id="针对插件的情况"><font><font>针对插件的情况</font></font></h3> + +<p><font><font>以前,插件在网络上是不可或缺的。还记得</font><font>你必须安装Adobe Flash Player才能在线观看电影的日子吗?并且你还会不断地收到关于更新Flash Player和Java运行环境的烦人警报。Web技术已经变得更加强大,那些日子已经结束了。对于大多数应用程序,现在是停止依赖插件传播内容,开始利用Web技术的时候了。</font></font></p> + +<ul> + <li><strong><font><font>扩大你对大家的影响力。</font></font></strong><font><font>每个人都有一个浏览器,但插件越来越少,特别是在移动用户中。</font><font>由于Web在很大程度上不需要依赖插件而运行,所以人们宁愿只是去竞争对手的网站而不是安装插件。</font></font></li> + <li><strong><font><font>从</font><font>Flash和其他插件附带</font><font>的</font></font><a href="http://webaim.org/techniques/flash/"><font><font>额外的可访问性问题</font></font></a><font><font>中</font>摆脱<font>。</font></font></strong></li> + <li><strong><font><font>避免额外的安全隐患。</font></font></strong><font><font>即使经过无数次补丁</font></font><a href="http://www.cvedetails.com/product/6761/Adobe-Flash-Player.html?vendor_id=53"><font><font>,</font></font></a><font><font> Adobe Flash也是</font><a href="http://www.cvedetails.com/product/6761/Adobe-Flash-Player.html?vendor_id=53"><font>非常不安全的</font></a><font>。</font><font>2015年,Facebook的首席安全官Alex Stamos甚至</font></font><a href="http://www.theverge.com/2015/7/13/8948459/adobe-flash-insecure-says-facebook-cso"><font><font>要求Adobe停止Flash。</font></font></a></li> +</ul> + +<p><font><font>那你该怎么办?</font><font>如果您需要交互性,HTML和</font></font><a href="https://developer.mozilla.org/en-US/docs/Glossary/JavaScript" title="JavaScript:JavaScript(JS)是一种编程语言,主要用于客户端来动态地脚本化网页,但也常常是服务器端的。"><font><font>JavaScript</font></font></a><font><font>可以轻松地为您完成工作,而不需要Java小程序或过时的ActiveX / BHO技术。</font><font>您可以使用</font></font><a href="/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/Video_and_audio_content"><font><font>HTML5视频</font></font></a><font><font>来满足媒体需求,</font><font>矢量图形</font></font><a href="/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web"><font><font>SVG</font></font></a><font><font>,以及</font><font>复杂图像和动画</font></font><a href="/zh-CN/docs/Web/API/Canvas_API/Tutorial"><font><font>画布</font></font></a><font><font>。</font></font><a href="https://plus.google.com/+PeterElst/posts/P5t4pFhptvp"><font><font>彼得·埃尔斯特(Peter Elst)几年前已经提到</font></font></a><font><font>,对于工作Adobe Flash极少是正确的工具,除了专门的游戏和商业应用。对于ActiveX,即使微软的</font></font><a href="https://developer.mozilla.org/en-US/docs/Glossary/Microsoft_Edge" title="Edge:Microsoft Edge是一种免费的图形Web浏览器,与Microsoft Windows捆绑在一起,由Microsoft自2014年开始。最初称为Spartan,Edge取代了长期以来的Microsoft浏览器Internet Explorer。"><font><font>Edge</font></font></a><font><font>浏览器也不再支持。</font></font></p> + +<h2 id="总结">总结</h2> + +<p><font><font>在Web文档中嵌入其他内容这一主题可以很快变得非常复杂,因此在本文中,我们尝试以一种简单而熟悉的方式来介绍它,这种介绍方式将立即显示出相关性,同时仍暗示了一些涉及更高级功能的技术。刚开始,除了嵌入第三方内容(如地图和视频),您不太可能在网页上使用到嵌入技术。当你变得更有经验时,你可能会开始为他们找到更多的用途。</font></font></p> + +<p><font><font>除了我们在这里讨论的那些外,还有许多涉及嵌入外部内容的技术。我们看到了一些在前面的文章中出现的,如</font></font><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video" title="使用HTML <video>元素将视频内容嵌入到文档中。"><code><video></code></a><font><font>,</font></font><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/audio" title="HTML <audio>元素用于在文档中嵌入声音内容。 它可能包含一个或多个音频源,使用src属性或<source>元素表示:浏览器将选择最合适的一个。 它也可以是流媒体的目的地,使用MediaStream。"><code><audio></code></a><font><font>和</font></font><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img" title="HTML <img>元素表示文档中的图像。"><code><img></code></a><font><font>,但还有其它的有待关注,如 </font></font><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas" title="使用HTML <canvas>元素与canvas脚本API来绘制图形和动画。"><code><canvas></code></a><font><font>用于JavaScript生成的2D和3D图形,</font></font><code><a href="https://developer.mozilla.org/en-US/docs/Web/SVG/Element/svg" title="关于此的文件尚未写入; 请考虑贡献!"><svg></a></code>用于<font><font>嵌入矢量图形</font></font><font><font>。</font><font>我们将在此学习模块的下一篇文章中学习</font></font><a href="https://developer.mozilla.org/en-US/docs/Web/SVG"><font><font>SVG</font></font></a><font><font>。</font></font></p> + +<p>{{PreviousMenuNext("Learn/HTML/Multimedia_and_embedding/Video_and_audio_content", "Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web", "Learn/HTML/Multimedia_and_embedding")}}</p> diff --git a/files/zh-cn/learn/html/tables/advanced/index.html b/files/zh-cn/learn/html/tables/advanced/index.html new file mode 100644 index 0000000000..66726e276e --- /dev/null +++ b/files/zh-cn/learn/html/tables/advanced/index.html @@ -0,0 +1,461 @@ +--- +title: HTML表格高级特性和可访问性 +slug: Learn/HTML/Tables/Advanced +tags: + - HTML + - scope + - table + - tbody + - tfoot + - thead + - 初学者 + - 可访问性 + - 学习 + - 标题 + - 高级 +translation_of: Learn/HTML/Tables/Advanced +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/HTML/Tables/Basics", "Learn/HTML/Tables/Structuring_planet_data", "Learn/HTML/Tables")}}</div> + +<p class="summary">这个模块的第二篇文章中,我们来看一下 HTML 表格更高级的功能,比如像 表格的标题/摘要,以及将你表格中的各行分组成头部、正文、页脚部分,提高视力受损用户的可访问性。</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">学习本章节的前提条件:</th> + <td>HTML 的基础知识 (see <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML">Introduction to HTML</a>).</td> + </tr> + <tr> + <th scope="row">目的:</th> + <td>学习 HTML 表格进一步的功能,以及表格的无障碍访问性。</td> + </tr> + </tbody> +</table> + +<h2 id="使用_<caption>_为你的表格增加一个标题">使用 <caption> 为你的表格增加一个标题</h2> + +<p>你可以为你的表格增加一个标题,通过 {{htmlelement("caption")}} 元素,再把 {{htmlelement("caption")}} 元素放入 {{htmlelement("table")}} 元素中. 你应该把它放在<code><table></code> 标签的下面。</p> + +<pre class="brush: html"><table> + <caption>Dinosaurs in the Jurassic period</caption> + + ... +</table></pre> + +<p>从上面简单的例子可以推断,标题意味着包含对于表格内容的描述,这对那些希望可以快速浏览网页中的表格对他们是否有帮助的读者们来说,是非常好的功能。特别是盲人用户,不需要让屏幕阅读设备读出很多单元格的内容,来让用户了解这张表格讲的是什么,而是可以依靠标题的内容,来决定是否需要了解更详细的内容。</p> + +<p>标题就放在 <code><table></code> 标签的下面。</p> + +<div class="note"> +<p><strong>注意</strong>: 这个 {{htmlattrxref("summary","table")}} 属性也可以在<code><table></code> 元素中使用,用来提供一段描述,同样可以被屏幕阅读设备阅读。我们推荐使用 <code><caption></code> 元素来代替使用,因为 <code>summary</code> 被 HTML5 规范, {{glossary("deprecated")}} (废除了),也不能被视力正常的用户阅读。 (它不会出现在页面上)</p> +</div> + +<h3 id="动手练习_添加一个标题">动手练习: 添加一个标题</h3> + +<p>我们来试试看吧,回顾一下我们在之前的文章中第一次遇到的例子。.</p> + +<ol> + <li>打开你的语言老师的学校时间表,就是 <a href="/en-US/docs/Learn/HTML/Tables/Basics#Active_learning_colgroup_and_col">HTML Table Basics</a> 结尾中的例子,或者把 <a href="https://github.com/mdn/learning-area/blob/master/html/tables/basic/timetable-fixed.html">timetable-fixed.html</a> 文件复制下面.</li> + <li>为表格添加一个合适的标题。</li> + <li>保存你的代码,然后用浏览器打开,看看你的表格是什么样的。</li> +</ol> + +<div class="note"> +<p><strong>注意</strong>:你也可以在 GitHub 上找到我们的版本 <a href="https://github.com/mdn/learning-area/blob/master/html/tables/advanced/timetable-caption.html">timetable-caption.html</a> (<a href="https://mdn.github.io/learning-area/html/tables/advanced/timetable-caption.html">see it live also</a>).</p> +</div> + +<h2 id="添加_<thead>_<tfoot>_和_<tbody>_结构">添加 <thead>, <tfoot>, 和 <tbody> 结构</h2> + +<p>由于你的表格在结构上有点复杂,如果把它们定义得更加结构化,那会帮助我们更能了解结构。一个明确的方法是使用 {{htmlelement("thead")}}, {{htmlelement("tfoot")}},和 {{htmlelement("tbody")}}, 这些元素允许你把表格中的部分标记为表头、页脚、正文部分。</p> + +<p>这些元素不会使表格更易于屏幕阅读器用户访问,也不会造成任何视觉上的改变。然而,它们在应用样式和布局上会起到作用,可以更好地让 CSS 应用到表格上。给你一些有趣的例子,在长表格的情况下,你可以在每个打印页面上使表格页眉和页脚重复,你也可以让表格的正文部分显示在一个单独的页面上,并通过上下滚动来获得内容。</p> + +<p>试着使用它们:</p> + +<ul> + <li> <code><thead></code> 需要嵌套在 table 元素中,放置在头部的位置,因为它通常代表第一行,第一行中往往都是每列的标题,但是不是每种情况都是这样的。如果你使用了 {{htmlelement("col")}}/{{htmlelement("colgroup")}} 元素,那么 <code><thead></code>元素就需要放在它们的下面。</li> + <li> <code><tfoot></code> 需要嵌套在 table 元素中,放置在底部 (页脚)的位置,一般是最后一行,往往是对前面所有行的总结,比如,你可以按照预想的方式将<code><tfoot></code>放在表格的底部,或者就放在 <code><thead></code> 的下面。(浏览器仍将它呈现在表格的底部)</li> + <li> <code><tbody></code> 需要嵌套在 table 元素中,放置在 <code><thead></code>的下面或者是 <code><tfoot></code> 的下面,这取决于你如何设计你的结构。(<code><tfoot></code>放在<code><thead></code>下面也可以生效.)</li> +</ul> + +<div class="note"> +<p><strong>注意</strong>: <code><tbody></code> 总是包含在每个表中,如果你没有在代码中指定它,那就是隐式的。可以来验证一下,打开一个你之前没有包含 <code><tbody></code> 的例子,然后在你的 <a href="/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools">browser developer tools</a> 中观察你的代码,你会看到浏览器为你添加了这个标签。你也许会想问,为什么你应该在所有表中都需要这个元素,因为它可以让你更好地控制表格结构和样式。</p> +</div> + +<h3 id="动手练习_添加表格结构">动手练习: 添加表格结构</h3> + +<p>让我们动手使用这些新元素。</p> + +<ol> + <li>首先,把 <a href="https://github.com/mdn/learning-area/blob/master/html/tables/advanced/spending-record.html">spending-record.html</a> 和 <a href="https://github.com/mdn/learning-area/blob/master/html/tables/advanced/minimal-table.css">minimal-table.css</a> 拷贝到你的本地环境。</li> + <li>尝试在浏览器中打开它,你会发现看起来不错,但是它可以被改善得更好。 "SUM" 行包含了已经使用的金额的总和,不过它出现在了错误的位置,以及代码中还遗失了一些细节。</li> + <li>将明显的标题行改为使用 <code><thead></code> 元素,"SUM" 行使用 <code><tfoot></code> 元素,剩余的内容使用 <code><tbody></code> 元素。</li> + <li>先保存,再刷新。你会看到,添加了 <code><tfoot></code> 元素后,导致 "SUM" 这行跑到了表格的底部。</li> + <li>接着, 添加一个 {{htmlattrxref("colspan","td")}} 属性,使 "SUM" 单元格占 4 个单元格的位置,所以实际数字是显示在 “Cost” 列的底部。</li> + <li>让我们为表格添加一些简单的额外属性,能够让你理解这些属性是如何帮助更好地让表格应用 CSS 的。在你的 HTML 文件的 head 标签部分,你会看到一个空的 {{htmlelement("style")}} 元素. 在 style 元素中添加下列 CSS 代码: + <pre class="brush: css">tbody { + font-size: 90%; + font-style: italic; +} + +tfoot { + font-weight: bold; +} +</pre> + </li> + <li>先保存,再刷新,然后观察一下结果。如果没有 <code><tbody></code> 和 <code><tfoot></code> 元素,你也许会写更加复杂的选择器来应用同样的样式。</li> +</ol> + +<div class="note"> +<p><strong>注意</strong>: 我们并不期望目前你可以理解所有 CSS 的内容。当你经过我们的 CSS 模块的时候,你应该会了解更多 (<a href="/zh_CN/docs/Learn/CSS/Introduction_to_CSS">Introduction to CSS</a> 是一个好的起点;我们也有专门的文章 <a href="/zh_CN/docs/Learn/CSS/Styling_boxes/Styling_tables">styling tables</a>).</p> +</div> + +<p>你完成的表格应该如下所示:</p> + +<div class="hidden"> +<h6 id="Hidden_example">Hidden example</h6> + +<pre class="brush: html"><!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>My spending record</title> + <style> + + html { + font-family: sans-serif; + } + + table { + border-collapse: collapse; + border: 2px solid rgb(200,200,200); + letter-spacing: 1px; + font-size: 0.8rem; + } + + td, th { + border: 1px solid rgb(190,190,190); + padding: 10px 20px; + } + + th { + background-color: rgb(235,235,235); + } + + td { + text-align: center; + } + + tr:nth-child(even) td { + background-color: rgb(250,250,250); + } + + tr:nth-child(odd) td { + background-color: rgb(245,245,245); + } + + caption { + padding: 10px; + } + + tbody { + font-size: 90%; + font-style: italic; + } + + tfoot { + font-weight: bold; + } + </style> + </head> + <body> + <table> + <caption>How I chose to spend my money</caption> + <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> + + </body> +</html></pre> +</div> + +<p>{{ EmbedLiveSample('Hidden_example', '100%', 300, "", "", "hide-codepen-jsfiddle") }}</p> + +<div class="note"> +<p><strong>注意</strong>: 你也可以在 GitHub 上找到 <a href="https://github.com/mdn/learning-area/blob/master/html/tables/advanced/spending-record-finished.html">spending-record-finished.html</a> (<a href="https://mdn.github.io/learning-area/html/tables/advanced/spending-record-finished.html">see it live also</a>).</p> +</div> + +<h2 id="嵌套表格">嵌套表格</h2> + +<p>在一个表格中嵌套另外一个表格是可能的,只要你包含完整的结构,包括 <code><table></code> 元素。这样通常是不建议的,因为这种做法会使标记看上去很难理解,对使用屏幕阅读的用户来说,可访问性也降低了。以及在很多情况下,也许你只需要插入额外的 单元格/行/列 到已有的表格中。然而有时候是必要的,比如你想要从其他资源中更简单地导入内容。</p> + +<p>下面的代码演示了一个简单的嵌套表格:</p> + +<pre class="brush: html"><table id="table1"> + <tr> + <th>title1</th> + <th>title2</th> + <th>title3</th> + </tr> + <tr> + <td id="nested"> + <table id="table2"> + <tr> + <td>cell1</td> + <td>cell2</td> + <td>cell3</td> + </tr> + </table> + </td> + <td>cell2</td> + <td>cell3</td> + </tr> + <tr> + <td>cell4</td> + <td>cell5</td> + <td>cell6</td> + </tr> +</table></pre> + +<p>输出看起来是这样的:</p> + +<table id="table1"> + <tbody> + <tr> + <th>title1</th> + <th>title2</th> + <th>title3</th> + </tr> + <tr> + <td id="nested"> + <table id="table2"> + <tbody> + <tr> + <td>cell1</td> + <td>cell2</td> + <td>cell3</td> + </tr> + </tbody> + </table> + </td> + <td>cell2</td> + <td>cell3</td> + </tr> + <tr> + <td>cell4</td> + <td>cell5</td> + <td>cell6</td> + </tr> + </tbody> +</table> + +<h2 id="对于视力受损的用户的表格">对于视力受损的用户的表格</h2> + +<p>让我们简要回顾一下如何使用数据表。一个表格可以是一个便利的工具,或者让我们快速访问数据,并允许我们查找不同的值。比如,你只需要稍微看一眼下列的表格,你就能得知 2016 年 8 月份在 Gent 出售了多少个 Rings (戒指)。为了理解信息,我们让数据与列标题或行标题之间建立视觉联系。</p> + +<table> + <caption>Items Sold August 2016</caption> + <tbody> + <tr> + <td></td> + <td></td> + <th colspan="3" scope="colgroup">Clothes</th> + <th colspan="2" scope="colgroup">Accessories</th> + </tr> + <tr> + <td></td> + <td></td> + <th scope="col">Trousers</th> + <th scope="col">Skirts</th> + <th scope="col">Dresses</th> + <th scope="col">Bracelets</th> + <th scope="col">Rings</th> + </tr> + <tr> + <th rowspan="3" scope="rowgroup">Belgium</th> + <th scope="row">Antwerp</th> + <td>56</td> + <td>22</td> + <td>43</td> + <td>72</td> + <td>23</td> + </tr> + <tr> + <th scope="row">Gent</th> + <td>46</td> + <td>18</td> + <td>50</td> + <td>61</td> + <td>15</td> + </tr> + <tr> + <th scope="row">Brussels</th> + <td>51</td> + <td>27</td> + <td>38</td> + <td>69</td> + <td>28</td> + </tr> + <tr> + <th rowspan="2" scope="rowgroup">The Netherlands</th> + <th scope="row">Amsterdam</th> + <td>89</td> + <td>34</td> + <td>69</td> + <td>85</td> + <td>38</td> + </tr> + <tr> + <th scope="row">Utrecht</th> + <td>80</td> + <td>12</td> + <td>43</td> + <td>36</td> + <td>19</td> + </tr> + </tbody> +</table> + +<p>但假设你无法通过视觉关联这些数据呢? 那么你应该如何阅读上述的表格? 视力受损的用户经常使用一个屏幕阅读设备来为他们读出网页上的信息。对于盲人来说,阅读简单的文字没有什么问题,但是要理解一张表格的内容,这就有一些难度了。虽然,使用正确的标记,我们可以用程序化来代替视觉关联。</p> + +<div class="note"> +<p><strong>注意</strong>: 根据<a href="http://www.who.int/zh/news-room/fact-sheets/detail/blindness-and-visual-impairment" title="视力损害和盲症">世界卫生组织 2017 年的数据</a>,大约有 2.53 亿人患有视觉障碍。</p> +</div> + +<p>本篇文章提供了更一步的技术来使表格的可访问性尽可能地提高。</p> + +<h3 class="attTitle" id="使用列和行的标题">使用列和行的标题</h3> + +<p>屏幕阅读设备会识别所有的标题,然后在它们和它们所关联的单元格之间产生编程关联。列和行标题的组合将标识和解释每个单元格中的数据,以便屏幕阅读器用户可以类似于视力正常的用户的操作来理解表格。</p> + +<p>我们之前的文章就提到过这一点,可见 <a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Tables/Basics#Adding_headers_with_%3Cth%3E_elements">Adding headers with <th> elements</a>.</p> + +<h3 class="attTitle" id="scope_属性">scope 属性</h3> + +<p>本篇文章的一个新话题是 {{htmlattrxref("scope","th")}} 属性,可以添加在<code><th></code> 元素中,用来帮助屏幕阅读设备更好地理解那些标题单元格,这个标题单元格到底是列标题呢,还是行标题。比如: 回顾我们之前的支出记录示例,你可以明确地将列标题这样定义:</p> + +<pre class="brush: html"><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></pre> + +<p>以及每一行都可以这样定义一个行标题 (如果我们已经使用了 th 和 td 元素):</p> + +<pre class="brush: html"><tr> + <th scope="row">Haircut</th> + <td>Hairdresser</td> + <td>12/09</td> + <td>Great idea</td> + <td>30</td> +</tr></pre> + +<p>屏幕阅读设备会识别这种结构化的标记,并一次读出整列或整行,比如:</p> + +<p><code>scope</code> 还有两个可选的值 : <code>colgroup</code> 和 <code>rowgroup</code>。这些用于位于多个列或行的顶部的标题。 如果你回顾这部分文章开始部分的 "Items Sold August 2016" 表格。你会看到 "Clothes" 单元格在"Trousers", "Skirts", 和 "Dresses" 单元格的上面。这几个单元格都应该被标记为 (<code><th></code>),但是 "Clothes" 是一个位于顶部且定义了其他三个子标题的标题。 因此 "Clothes" 应该有一个 <code>scope="colgroup"</code>属性,而另外三个子标题应该有 <code>scope="col"</code>属性。</p> + +<h3 class="attTitle" id="id_和标题属性">id 和标题属性</h3> + +<p>如果要替代 <code>scope</code> 属性,可以使用 {{htmlattrxref("id")}} 和 {{htmlattrxref("headers", "td")}} 属性来创造标题与单元格之间的联系。使用方法如下:</p> + +<ol> + <li>为每个<code><th></code> 元素添加一个唯一的 <code>id</code> 。</li> + <li>为每个 <code><td></code> 元素添加一个 <code>headers</code> 属性。每个单元格的<code>headers</code> 属性需要包含它从属于的所有标题的id,之间用空格分隔开。</li> +</ol> + +<p>这会给你的HTML表格中每个单元格的位置一个明确的定义。像一个电子表格一样,通过 headers 属性来定义属于哪些行或列。为了让它工作良好,表格同时需要列和行标题。</p> + +<p>回到我们的花费成本示例,前两个片段可以重写为:</p> + +<pre class="brush: html"><thead> + <tr> + <th id="purchase">Purchase</th> + <th id="location">Location</th> + <th id="date">Date</th> + <th id="evaluation">Evaluation</th> + <th id="cost">Cost (€)</th> + </tr> +</thead> +<tbody> +<tr> + <th id="haircut">Haircut</th> + <td headers="location haircut">Hairdresser</td> + <td headers="date haircut">12/09</td> + <td headers="evaluation haircut">Great idea</td> + <td headers="cost haircut">30</td> +</tr> + + ... + +</tbody></pre> + +<div class="note"> +<p><strong>注意</strong>: 这个放进为标题单元格和数据单元格之间创造了非常精确的联系。但是这个方法使用了大量的标记,所以容错率比较低。使用 <code>scope</code> 的方法对于大多数表格来说,也够用了。</p> +</div> + +<h3 id="动手练习_使用_scope_和_headers">动手练习: 使用 scope 和 headers</h3> + +<ol> + <li>对于这个最后的练习,首先把 <a href="https://github.com/mdn/learning-area/blob/master/html/tables/advanced/items-sold.html">items-sold.html</a> 和 <a href="https://github.com/mdn/learning-area/blob/master/html/tables/advanced/minimal-table.css">minimal-table.css</a>,拷贝到你的本地环境。</li> + <li>现在尝试添加适当的 <code>scope</code> 属性来让表格变得更加恰当。</li> + <li>最后,尝试把未添加 <code>scope</code> 属性的源文件再复制一份。这次使用 <code>id</code> 和 <code>headers</code> 属性让表格变得更加恰当。</li> +</ol> + +<div class="note"> +<p><strong>注意</strong>: 你可以根据我们完成的例子检查你的工作,请看 <a href="https://github.com/mdn/learning-area/blob/master/html/tables/advanced/items-sold-scope.html">items-sold-scope.html</a> (<a href="https://mdn.github.io/learning-area/html/tables/advanced/items-sold-scope.html">also see this live</a>) 和 <a href="https://github.com/mdn/learning-area/blob/master/html/tables/advanced/items-sold-headers.html">items-sold-headers.html</a> (<a href="https://mdn.github.io/learning-area/html/tables/advanced/items-sold-headers.html">see this live too</a>).</p> +</div> + +<h2 id="总结">总结</h2> + +<p>关于 HTML 表格你还可以学习其他一些东西,但是我们目前已经把大部分你需要知道的内容都告诉你了。在此刻,如果你想学习关于 HTML 表格的样式,可以阅读 <a href="/en-US/docs/Learn/CSS/Styling_boxes/Styling_tables">Styling Tables</a>.</p> + +<div>{{PreviousMenuNext("Learn/HTML/Tables/Basics", "Learn/HTML/Tables/Structuring_planet_data", "Learn/HTML/Tables")}}</div> diff --git a/files/zh-cn/learn/html/tables/basics/index.html b/files/zh-cn/learn/html/tables/basics/index.html new file mode 100644 index 0000000000..1198158b86 --- /dev/null +++ b/files/zh-cn/learn/html/tables/basics/index.html @@ -0,0 +1,497 @@ +--- +title: HTML 表格 入门 +slug: Learn/HTML/Tables/Basics +tags: + - colgroup + - colspan + - row + - rowspan + - 初学者 + - 单元格 + - 基础 + - 学习 + - 表格 +translation_of: Learn/HTML/Tables/Basics +--- +<div>{{LearnSidebar}}</div> + +<div>{{NextMenu("Learn/HTML/Tables/Advanced", "Learn/HTML/Tables")}}</div> + +<p class="summary">本文将从HTML表格开始,介绍一些基本的内容,如行和单元格、标题、使单元格跨越多个列和行,以及如何将列中的所有单元组合在一起进行样式化。</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">前置知识:</th> + <td>HTML基本概念 (参见 <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML">Introduction to HTML</a>)。</td> + </tr> + <tr> + <th scope="row">目标:</th> + <td>了解熟悉HTML表格基本知识。</td> + </tr> + </tbody> +</table> + +<h2 id="什么是表格?">什么是表格?</h2> + +<p>表格是由行和列组成的结构化数据集(表格数据),它能够使你简捷迅速地查找某个表示不同类型数据之间的某种关系的值 。比如说,某个人和他的年龄,一天或是一周,当地游泳池的时间表 。</p> + +<p><img alt="A sample table showing names and ages of some people - Chris 38, Dennis 45, Sarah 29, Karen 47." src="https://mdn.mozillademos.org/files/14583/numbers-table.png" style="display: block; height: 156px; margin: 0px auto; width: 350px;"></p> + +<p><img alt="A swimming timetable showing a sample data table" src="https://mdn.mozillademos.org/files/14587/swimming-timetable.png" style="display: block; height: 301px; margin: 0px auto; width: 794px;"></p> + +<p>表格在人类社会中很常见,而且已经存在很长时间了,下面这张1800年的美国人口普查文件中就可以证明:</p> + +<p><img alt="A very old parchment document; the data is not easily readable, but it clearly shows a data table being used." src="https://mdn.mozillademos.org/files/14585/1800-census.jpg" style="display: block; height: 505px; margin: 0px auto; width: 800px;"></p> + +<p>因此,HTML的创建者们提供了一种方法来构建和呈现web上的表格数据,这也就不足为奇了。</p> + +<h3 id="表格如何工作?">表格如何工作?</h3> + +<p>表格的一个特点就是严格. 通过在行和列的标题之间进行视觉关联的方法,就可以让信息能够很简单地被解读出来。观察下面的示例表格,然后找一个单数人称代词,这个单数人称代词是用于第三人称的, 用于女性的, 用作句子中的对象. 你可以把相应的行和列的标题关联起来,找到答案。</p> + +<p>人称代词</p> + +<table> + <tbody> + <tr> + <th colspan="3"></th> + <th scope="col">Subject</th> + <th scope="col">Object</th> + </tr> + <tr> + <th rowspan="5" scope="rowgroup">单数</th> + <th colspan="2" scope="row">第一人称</th> + <td>I</td> + <td>me</td> + </tr> + <tr> + <th colspan="2" scope="row">第二人称</th> + <td>you</td> + <td>you</td> + </tr> + <tr> + <th rowspan="3" scope="rowgroup">第三人称</th> + <th class="symbol" scope="row">♂</th> + <td>he</td> + <td>him</td> + </tr> + <tr> + <th class="symbol" scope="row">♀</th> + <td>she</td> + <td>her</td> + </tr> + <tr> + <th class="symbol" scope="row">o</th> + <td>it</td> + <td>it</td> + </tr> + <tr> + <th rowspan="3" scope="rowgroup">复数</th> + <th colspan="2" scope="row">第一人称</th> + <td>we</td> + <td>us</td> + </tr> + <tr> + <th colspan="2" scope="row">第二人称</th> + <td>you</td> + <td>you</td> + </tr> + <tr> + <th colspan="2" scope="row">第三人称</th> + <td>they</td> + <td>them</td> + </tr> + </tbody> +</table> + +<p>正确完成后, 即使是盲人也可以解析 HTML 表格中的数据,一个成功的 HTML 表格应该做到无论用户是视力正常还是视力受损,都能提高用户的体验。</p> + +<h3 id="表格风格">表格风格</h3> + +<p>你可以在 GitHub 上找到上面表格的 <a href="https://github.com/mdn/learning-area/blob/master/html/tables/basic/personal-pronouns.html">HTML源码</a> ; 先去看看, 当然也可以看看这个 <a href="http://mdn.github.io/learning-area/html/tables/basic/personal-pronouns.html">look at the live example</a>! 你也许会注意到一件事情,那就是这个表格看上去可读性不是很好,那是因为现在这个页面上面的那个表格通过 MDN 站点添加了一些样式, 而 GitHub 上面的并没有添加。</p> + +<p>不要幻想; 为了能够让表格在网页上有效, 你需要提供一些 CSS 的样式信息,以及尽可能好的 HTML 固定结构. 在这个模块中,我们将专注于 HTML 部分; 在你完成这里的内容之后,你可以浏览 <a href="/en-US/docs/Learn/CSS/Styling_boxes/Styling_tables">Styling tables</a> 来了解 CSS 的部分。</p> + +<p>虽然在这个模块中我们不会专注于 CSS, 但是我们提供了一个较小的 CSS 样式表让你使用,和默认的没有采用任何 CSS 样式的表相比,表格会更加可读。 你可以在 <a href="https://github.com/mdn/learning-area/blob/master/html/tables/basic/minimal-table.css">stylesheet here</a> 获取样式表,以及在 <a href="https://github.com/mdn/learning-area/blob/master/html/tables/basic/blank-template.html">HTML template</a> 获取 HTML 文件来应用样式表,这些会让你在 “测试 HTML 表格” 中有一个好的起点。</p> + +<div class="note"> +<p><strong>注意</strong>: 也可以看下 <a href="http://mdn.github.io/learning-area/html/tables/basic/personal-pronouns-styled.html">personal_pronouns table with this styling applied</a> 这个版本, 这个是应用了 CSS 以后表格看上去的样子。</p> +</div> + +<h3 id="什么时候你不应该使用_HTML_表格">什么时候你不应该使用 HTML 表格?</h3> + +<p>HTML 表格 应该用于表格数据 ,这正是 HTML 表格设计出来的用途. 不幸的是, 许多人习惯用 HTML 表格来实现网页布局, e.g. 一行包含 header, 一行包含几列内容, 一行包含 footer, etc. 你可以在我们的 <a href="/en-US/docs/Learn/Accessibility">Accessibility Learning Module</a> 中的 <a href="/en-US/docs/Learn/Accessibility/HTML#Page_layouts">Page Layouts</a> 获得更多细节内容和一个示例。这种做法以前是很常见的,因为以前 CSS 在不同浏览器上的兼容性比较糟糕 ; 表格布局现在不太普遍,但您可能仍然会在网络的某些角落看到它们。</p> + +<p>简单来说, 使用表格布局而不使用 <a href="/en-US/docs/Learn/CSS/CSS_layout">CSS layout techniques</a> 是很糟糕的. 主要的理由有以下几个:</p> + +<ol> + <li><strong>表格布局减少了视觉受损的用户的可访问性</strong>: <a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Accessibility#Screenreaders">屏幕阅读器</a>, 被盲人所使用, 解析存在于 HTML 页面上的标签,然后为用户读出其中的内容。因为对于布局来说,表格不是一个正确的工具, 使用的标记比使用 CSS 布局技术更复杂, 所以屏幕阅读器的输出会让他们的用户感到困惑。</li> + <li><strong>表格会产生很多标签</strong>: 正如刚才提到的, 表格布局通常会比正确的布局技术涉及更复杂的标签结构,这会导致代码变得更难于编写、维护、调试.</li> + <li><strong>表格不能自动响应</strong>: 当你使用正确的布局容器 (比如 {{htmlelement("header")}}, {{htmlelement("section")}}, {{htmlelement("article")}}, 或是 {{htmlelement("div")}}), 它们的默认宽度是父元素的 100%. 而表格的的默认大小是根据其内容而定的。因此,需要采取额外的措施来获取表格布局样式,以便有效地在各种设备上工作。</li> +</ol> + +<h2 id="动手练习_创建你的第一个表格">动手练习: 创建你的第一个表格</h2> + +<p>对于表格的理论知识,我们已经说了很多了,所以, 让我们来看一个使用的例子,并建立一个简单的表格.</p> + +<ol> + <li>首先, 将 <a href="https://github.com/mdn/learning-area/blob/master/html/tables/basic/blank-template.html">blank-template.html</a> 和 <a href="https://github.com/mdn/learning-area/blob/master/html/tables/basic/minimal-table.css">minimal-table.css</a> 拷贝到你的本地环境上。</li> + <li>每一个表格的内容都包含在这两个标签中 : <strong><code><a href="/en-US/docs/Web/HTML/Element/table"><table></table></a></code></strong>. 在你的 HTML 的 {{htmlelement("body")}} 中添加这些内容。</li> + <li>在表格中,最小的内容容器是单元格, 是通过 <strong><code><a href="/en-US/docs/Web/HTML/Element/td"><td></a></code></strong> 元素创建的 ('td' 代表 'table data'). 把下面的内容添加到你的表格标签中: + <pre class="brush: html notranslate"><td>Hi, I'm your first cell.</td></pre> + </li> + <li>如果我们想要一行四个单元格,我们需要把这组标签拷贝三次,更新你表中的内容,让它看起来是这样的: + <pre class="brush: html notranslate"><td>Hi, I'm your first cell.</td> +<td>I'm your second cell.</td> +<td>I'm your third cell.</td> +<td>I'm your fourth cell.</td></pre> + </li> +</ol> + +<p>你会看到, 单元格不会放置在彼此的下方, 而是自动与同一行上的其他单元格对齐. 每个 <code><td></code> 元素 创建一个单独单元格,它们共同组成了第一行。我们添加的每个单元格都使行的长度变长。</p> + +<p>如果想让这一行停止增加,并让单元格从第二行开始,我们需要使用 <strong><code><a href="/en-US/docs/Web/HTML/Element/tr"><tr></a></code></strong> 元素 ('tr' 代表 'table row'). 让我们现在来证实一下。</p> + +<ol> + <li>把你已经创建好的 4 个单元格放入 <code><tr></code> 标签, 就像: + + <pre class="brush: html notranslate"><tr> + <td>Hi, I'm your first cell.</td> + <td>I'm your second cell.</td> + <td>I'm your third cell.</td> + <td>I'm your fourth cell.</td> +</tr></pre> + </li> + <li>现在你已经实现了一行,可以继续增加至两行、三行。每一行都需要一个额外的 <code><tr></code> 元素来包装,每个单元格的内容都应该写在 <code><td></code>中。</li> +</ol> + +<p>这样会产生一个如下所示的表:</p> + +<table> + <tbody> + <tr> + <td>Hi, I'm your first cell.</td> + <td>I'm your second cell.</td> + <td>I'm your third cell.</td> + <td>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> + </tbody> +</table> + +<div class="note"> +<p><strong>注意</strong>: 你也可以在 GitHub 中查看 <a href="https://github.com/mdn/learning-area/blob/master/html/tables/basic/simple-table.html">simple-table.html</a> (<a href="https://mdn.github.io/learning-area/html/tables/basic/simple-table.html">see it live also</a>).</p> +</div> + +<h2 id="使用_<th>_元素添加标题">使用 <th> 元素添加标题</h2> + +<p>现在,让我们把注意力转向表格标题,表格中的标题是特殊的单元格,通常在行或列的开始处,定义行或列包含的数据类型 (举个例子, 看到本篇文章中第一个示例中的 "单数" 或者 "Object" ). 为了说明它们为什么这么有用, 来看下面这个例子,首先是源代码:</p> + +<pre class="brush: html notranslate"><table> + <tr> + <td>&nbsp;</td> + <td>Knocky</td> + <td>Flor</td> + <td>Ella</td> + <td>Juan</td> + </tr> + <tr> + <td>Breed</td> + <td>Jack Russell</td> + <td>Poodle</td> + <td>Streetdog</td> + <td>Cocker Spaniel</td> + </tr> + <tr> + <td>Age</td> + <td>16</td> + <td>9</td> + <td>10</td> + <td>5</td> + </tr> + <tr> + <td>Owner</td> + <td>Mother-in-law</td> + <td>Me</td> + <td>Me</td> + <td>Sister-in-law</td> + </tr> + <tr> + <td>Eating Habits</td> + <td>Eats everyone's leftovers</td> + <td>Nibbles at food</td> + <td>Hearty eater</td> + <td>Will eat till he explodes</td> + </tr> +</table></pre> + +<p>这是表格实际呈现的效果:</p> + +<table> + <tbody> + <tr> + <td></td> + <td>Knocky</td> + <td>Flor</td> + <td>Ella</td> + <td>Juan</td> + </tr> + <tr> + <td>Breed</td> + <td>Jack Russell</td> + <td>Poodle</td> + <td>Streetdog</td> + <td>Cocker Spaniel</td> + </tr> + <tr> + <td>Age</td> + <td>16</td> + <td>9</td> + <td>10</td> + <td>5</td> + </tr> + <tr> + <td>Owner</td> + <td>Mother-in-law</td> + <td>Me</td> + <td>Me</td> + <td>Sister-in-law</td> + </tr> + <tr> + <td>Eating Habits</td> + <td>Eats everyone's leftovers</td> + <td>Nibbles at food</td> + <td>Hearty eater</td> + <td>Will eat till he explodes</td> + </tr> + </tbody> +</table> + +<p>这里的问题是:虽然你可以弄清楚发生了什么,但是尽可能的交叉参考数据并不容易。如果列和行的标题以某种方式出现,那将会更好。</p> + +<h3 id="动手练习_表格标题">动手练习: 表格标题</h3> + +<p>让我们来改进这个表格.</p> + +<ol> + <li>首先, 把 <a href="https://github.com/mdn/learning-area/blob/master/html/tables/basic/dogs-table.html">dogs-table.html</a> 和 <a href="https://github.com/mdn/learning-area/blob/master/html/tables/basic/minimal-table.css">minimal-table.css</a> 文件保存到你的本地环境,HTML 文件包含上文你看到的几种狗的数据。</li> + <li>为了将表格的标题在视觉上和语义上都能被识别为标题,你可以使用 <strong><code><a href="/en-US/docs/Web/HTML/Element/th"><th></a></code></strong> 元素 ('th' 代表 'table header'). 用法和 <code><td></code>是一样的,除了它表示为标题,不是普通的单元格以外。进入你的 HTML 文件, 将表格中应该是标题的 <code><td></code> 元素标记的内容,都改为用 <code><th></code> 元素标记。</li> + <li>保存你的 HTML 文件,然后在浏览器中加载,然后你应该会看到,现在的标题更像标题了。</li> +</ol> + +<div class="note"> +<p><strong>注意</strong>: 你可以在 GitHub 中找到完成的版本 <a href="https://github.com/mdn/learning-area/blob/master/html/tables/basic/dogs-table-fixed.html">dogs-table-fixed.html</a> (<a href="https://mdn.github.io/learning-area/html/tables/basic/dogs-table-fixed.html">see it live also</a>).</p> +</div> + +<h3 id="为什么标题是有用的">为什么标题是有用的?</h3> + +<p>我们已经给出了部分答案,当标题明显突出的时候,你可以更加简单地找到你想找的数据,设计上也会看起来更好。</p> + +<div class="note"> +<p><strong>注意</strong>: 即使你不给表格添加你自己的样式,表格标题也会带有一些默认样式:加粗和居中,让标题可以突出显示。</p> +</div> + +<p>表格标题也有额外的好处,随着 <code>scope</code> 属性 (我们将在下一篇文章中了解到),这个属性允许你让表格变得更加无障碍,每个标题与相同行或列中的所有数据相关联。屏幕阅读设备能一次读出一列或一行的数据,这是非常有帮助的。</p> + +<h2 id="允许单元格跨越多行和列">允许单元格跨越多行和列</h2> + +<p>有时我们希望单元格跨越多行或多列。以下是一个简单的例子,显示了一些常见动物的名字。在某些情况下,我们要显示动物名称旁边的男性和女性的名字。有时候我们又不需要,那不需要的情况下,我们希望写着动物的名字的单元格的宽度可以是两个单元格的宽度 (因为写着名字的行会有两列,而没有写名字的行只有一列,行的宽度是不一样的)。</p> + +<p>一开始的标记写法是这样的:</p> + +<pre class="brush: html notranslate"><table> + <tr> + <th>Animals</th> + </tr> + <tr> + <th>Hippopotamus</th> + </tr> + <tr> + <th>Horse</th> + <td>Mare</td> + </tr> + <tr> + <td>Stallion</td> + </tr> + <tr> + <th>Crocodile</th> + </tr> + <tr> + <th>Chicken</th> + <td>Hen</td> + </tr> + <tr> + <td>Rooster</td> + </tr> +</table></pre> + +<p>但是输出的结果不是我们想要的:</p> + +<table> + <tbody> + <tr> + <th>Animals</th> + </tr> + <tr> + <th>Hippopotamus</th> + </tr> + <tr> + <th>Horse</th> + <td>Mare</td> + </tr> + <tr> + <td>Stallion</td> + </tr> + <tr> + <th>Crocodile</th> + </tr> + <tr> + <th>Chicken</th> + <td>Hen</td> + </tr> + <tr> + <td>Rooster</td> + </tr> + </tbody> +</table> + +<p>我们需要一个方法,让 "Animals", "Hippopotamus", 和 "Crocodile" 的单元格的宽度变为两个单元格, "Horse" 和 "Chicken" 的高度变为两行 (因为要拥有一个男性名字和女性名字,可以先看效果图)。幸好, 表格中的标题和单元格有 <code>colspan</code> 和 <code>rowspan</code> 属性,这两个属性可以帮助我们实现这些效果。这两个属性接受一个没有单位的数字值,数字决定了它们的宽度或高度是几个单元格。比如, <code>colspan="2"</code> 使一个单元格的宽度是两个单元格。</p> + +<p>让我们使用 <code>colspan</code> 和 <code>rowspan</code> 来改进现有的表格。</p> + +<ol> + <li>首先,把 <a href="https://github.com/mdn/learning-area/blob/master/html/tables/basic/animals-table.html">animals-table.html</a> 和 <a href="https://github.com/mdn/learning-area/blob/master/html/tables/basic/minimal-table.css">minimal-table.css</a> 文件复制到你的本地环境,HTML 文件中包含了你刚才看到的动物示例的数据。</li> + <li>接着,使用 <code>colspan</code> 让 "Animals", "Hippopotamus", 和 "Crocodile" 占 2 个单元格的宽度。</li> + <li>最后,使用 <code>rowspan</code> 让 "Horse" 和 "Chicken" 占 2 个单元格的高度。</li> + <li>保存后,用浏览器打开你写的 HTML 文件,看看改进的地方。</li> +</ol> + +<div class="note"> +<p><strong>注意</strong>: 你也可以在 GitHub 上找到完成的版本 <a href="https://github.com/mdn/learning-area/blob/master/html/tables/basic/animals-table-fixed.html">animals-table-fixed.html</a> (<a href="https://mdn.github.io/learning-area/html/tables/basic/animals-table-fixed.html">see it live also</a>).</p> +</div> + +<table id="tabular" style="background-color: white;"> +</table> + +<h2 id="为表格中的列提供共同的样式">为表格中的列提供共同的样式</h2> + +<p>在我们继续介绍之前,我们将介绍本文中的最后一个功能。HTML有一种方法可以定义整列数据的样式信息:就是 <strong><code><a href="/en-US/docs/Web/HTML/Element/col"><col></a></code></strong> 和 <strong><code><a href="/en-US/docs/Web/HTML/Element/colgroup"><colgroup></a></code></strong> 元素。 它们存在是因为如果你想让一列中的每个数据的样式都一样,那么你就要为每个数据都添加一个样式,这样的做法是令人厌烦和低效的。你通常需要在列中的每个 <code><td></code> 或 <code><th></code> 上定义样式,或者使用一个复杂的选择器,比如 {{cssxref(":nth-child()")}}。</p> + +<p>下面是一个简单的示例:</p> + +<pre class="brush: html notranslate"><table> + <tr> + <th>Data 1</th> + <th style="background-color: yellow">Data 2</th> + </tr> + <tr> + <td>Calcutta</td> + <td style="background-color: yellow">Orange</td> + </tr> + <tr> + <td>Robots</td> + <td style="background-color: yellow">Jazz</td> + </tr> +</table></pre> + +<p>下面就是上述代码的结果:</p> + +<table> + <tbody> + <tr> + <th>Data 1</th> + <th style="background-color: yellow;">Data 2</th> + </tr> + <tr> + <td>Calcutta</td> + <td style="background-color: yellow;">Orange</td> + </tr> + <tr> + <td>Robots</td> + <td style="background-color: yellow;">Jazz</td> + </tr> + </tbody> +</table> + +<p>这样不太理想,因为我们不得不在列中的每个单元格中重复那些样式信息 (在真实的项目中,我们或许会设置一个 <code>class</code> 包含那三个单元格 ,然后在一个单独的样式表中定义样式). 为了舍弃这种做法,我们可以只定义一次,在 <code><col></code> 元素中。<code><col></code> 元素被规定包含在 <code><colgroup></code> 容器中,而 <code><colgroup></code>就在 <code><table></code> 标签的下方。我们可以通过如下的做法来创建与上面相同的效果:</p> + +<pre class="brush: html notranslate"><table> + <colgroup> + <col> + <col style="background-color: yellow"> + </colgroup> + <tr> + <th>Data 1</th> + <th>Data 2</th> + </tr> + <tr> + <td>Calcutta</td> + <td>Orange</td> + </tr> + <tr> + <td>Robots</td> + <td>Jazz</td> + </tr> +</table></pre> + +<p>我们使用了两个 <code><col></code>来定义“列的样式”,每一个<code><col></code>都会制定每列的样式,对于第一列,我们没有采取任何样式,但是我们仍然需要添加一个空的 <code><col></code> 元素,如果不这样做,那么我们的样式就会应用到第一列上,这和我们预想的不一样。</p> + +<p>如果你想把这种样式信息应用到每一列,我们可以只使用一个 <code><col></code> 元素,不过需要包含 span 属性,像这样:</p> + +<pre class="brush: html notranslate"><colgroup> + <col style="background-color: yellow" span="2"> +</colgroup></pre> + +<p>就像 <code>colspan</code> 和 <code>rowspan</code>, <code>span</code> 需要一个无单位的数字值,用来制定你想要让这个样式应用到表格中多少列</p> + +<h3 id="动手练习_colgroup_and_col">动手练习: colgroup and col</h3> + +<p>又到了需要你自己独立完成的时间了。</p> + +<p>下面你可以看到一位语言老师的时间表。星期五,她有一个新的课程,全天教荷兰语,但是在星期二和星期四的几个时间点,她也教德语。她想把那些包含她教学的日子的列高亮显示。</p> + +<p>{{EmbedGHLiveSample("learning-area/html/tables/basic/timetable-fixed.html", '100%', 320)}}</p> + +<p>通过下面这些步骤来重构这个表格。</p> + +<ol> + <li>首先,把 <a href="https://github.com/mdn/learning-area/blob/master/html/tables/basic/timetable.html">timetable.html</a> 文件复制到你的本地环境。这个 HTML 文件包含你在上文中看到的表格,不过是减去样式信息的。</li> + <li>在 table 的顶部添加一个 <code><colgroup></code> 元素,就放在 <code><table></code> 标签下面,<code><colgroup></code>可以添加 <code><col></code> 元素 (继续看下面剩余的步骤)。</li> + <li>第一列和第二列不需要应用样式。</li> + <li>为第三列添加一个背景颜色。<code>style</code> 属性是 <code>background-color:#97DB9A;</code></li> + <li>为第四列设置一个独立的宽度,<code>style</code> 属性是 <code>width: 42px;</code></li> + <li>为第五列添加一个背景颜色。<code>style</code> 属性是 <code>background-color: #97DB9A;</code></li> + <li>为第六列添加不同的背景颜色和边框,表示这是一个特殊的日子,表示她正在教一个新的课。 <code>style</code> 属性是 <code>background-color:#DCC48E; border:4px solid #C1437A;</code></li> + <li>最后两天是休息日,所以只需将它们设置为无背景颜色,但需要设置宽度;<code>style</code> 属性是 <code>width: 42px;</code></li> +</ol> + +<p>看看你是否能完成这个示例,如果你遇到了困难,或想要核对你完成的作品,你可以在 GitHub 上找到完成的版本 <a href="https://github.com/mdn/learning-area/blob/master/html/tables/basic/timetable-fixed.html">timetable-fixed.html</a> (<a href="https://mdn.github.io/learning-area/html/tables/basic/timetable-fixed.html">see it live also</a>)。</p> + +<h2 id="小结">小结</h2> + +<p>本章节仅仅包含了 HTML 表格的基础。在下一篇文章中,我们将介绍一些稍微更高级的表格功能,并开始考虑方便视力障碍的人士的访问</p> + +<div>{{NextMenu("Learn/HTML/Tables/Advanced", "Learn/HTML/Tables")}}</div> + +<div></div> + +<h2 id="在本单元中">在本单元中</h2> + +<ul> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Tables/Basics">HTML table basics</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Tables/Advanced">HTML table advanced features and accessibility</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Tables/Structuring_planet_data">Structuring planet data</a></li> +</ul> + +<div> +<article> +<ul> +</ul> +</article> +</div> diff --git a/files/zh-cn/learn/html/tables/index.html b/files/zh-cn/learn/html/tables/index.html new file mode 100644 index 0000000000..0bcc6695d7 --- /dev/null +++ b/files/zh-cn/learn/html/tables/index.html @@ -0,0 +1,44 @@ +--- +title: HTML 表格 +slug: Learn/HTML/Tables +tags: + - HTML + - Landing + - Module + - NeedsTranslation + - TopicStub + - 初学者 + - 指引 + - 文章 + - 表格 +translation_of: Learn/HTML/Tables +--- +<div>{{LearnSidebar}}</div> + +<p class="summary">在HTML中一个很普通的任务是构建表格数据,有大量的元素和属性是来满足这种需求的。只需要一点儿的CSS来设定风格,HTML让在web上显示表格数据变的很容易,例如你的学校的教学计划,你当地的游泳馆的时刻表, 或者是关于你最爱的恐龙或足球队的统计数据。这个模块会教给你所有你需要知道的关于用HTML构建表格数据的知识。</p> + +<h2 id="先决条件">先决条件</h2> + +<p>在你开始这一模块之前,你需要已经了解了HTML的基础知识——看<a href="/zh-CN/docs/Learn/HTML/Introduction_to_HTML">Introduction to HTML</a>.</p> + +<div class="note"> +<p><strong>Note</strong>: 如果你是在计算机/平板电脑等其他你无法创建文件的设备上的话,你可以尝试在在线代码编辑平台上运行代码例如 <a href="http://jsbin.com/">JSBin</a> 或 <a href="https://thimble.mozilla.org/">Thimble</a>.</p> +</div> + +<h2 id="向导">向导</h2> + +<p>本模块包含以下的文章</p> + +<dl> + <dt><a href="/zh-CN/docs/Learn/HTML/Tables/Basics">HTML 表格基础</a></dt> + <dd>本文将帮助你学习如何使用 HTML 格式,包括如行、列、表头、跨列的行或跨行的列等基本特性,以及如何将多行进行分组进行样式化。</dd> + <dt><a href="/zh-CN/docs/Learn/HTML/Tables/Advanced">HTML 表格高级功能与可访问性</a></dt> + <dd>在本模块第二篇文章中,我们将了解一些 HTML 表格的高级功能 —— 比如表名称/表摘要,因为可访问性的原因,将表格内容划分为表头、主体以及脚部等章节。</dd> +</dl> + +<h2 id="练习">练习</h2> + +<dl> + <dt><a href="/zh-CN/docs/Learn/HTML/Tables/Structuring_planet_data">构造行星的数据结构</a></dt> + <dd>在表格的练习中,我们向你提供了一些在我们太阳系的行星的数据,不妨你把它构造成一个HTML的表格吧。</dd> +</dl> diff --git a/files/zh-cn/learn/html/tables/structuring_planet_data/index.html b/files/zh-cn/learn/html/tables/structuring_planet_data/index.html new file mode 100644 index 0000000000..30a2e40606 --- /dev/null +++ b/files/zh-cn/learn/html/tables/structuring_planet_data/index.html @@ -0,0 +1,72 @@ +--- +title: 作业:构建行星数据 +slug: Learn/HTML/Tables/Structuring_planet_data +translation_of: Learn/HTML/Tables/Structuring_planet_data +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenu("Learn/HTML/Tables/Advanced", "Learn/HTML/Tables")}}</div> + +<p class="summary">在我们的表格评定中,我们为你提供有关太阳系中行星的一些数据,并让你将其结构化成HTML表。</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">学习本章的前提条件:</th> + <td>在尝试这个评定之前,你应该已经把这个模块的所有文章都学习完成了。</td> + </tr> + <tr> + <th scope="row">目的:</th> + <td>检测对 HTML 表格及相关功能的理解。</td> + </tr> + </tbody> +</table> + +<h2 id="起点">起点</h2> + +<p>要进行本测验,将 <a href="https://github.com/roy-tian/learning-area/blob/master/html/tables/assessment-start/blank-template.html">blank-template.html</a>, <a href="https://github.com/roy-tian/learning-area/blob/master/html/tables/assessment-start/minimal-table.css">minimal-table.css</a> 和 <a href="https://github.com/roy-tian/learning-area/blob/master/html/tables/assessment-start/planets-data.txt">planets-data.txt</a> 拷贝到本地。</p> + +<div class="note"> +<p><strong>注意</strong>: 另外, 你可以使用 <a class="external external-icon" href="https://jsbin.com/">JSBin</a> 或 <a class="external external-icon" href="https://thimble.mozilla.org/">Thimble</a> 来做你的测验。你可以把 HTML, CSS 和 JavaScript 粘贴到其中一个网上编辑器里。如果你使用的网上编辑器不支持 JavaScript/CSS 文件链接到 HTML 中使用,那么也可以使用 <code><script></code>/<code><style></code> 元素将它们直接写在你的 HTML 页面里。</p> +</div> + +<h2 id="项目概要">项目概要</h2> + +<p>你在学校工作; 目前,你的学生正在学习太阳系的行星,然后你想为他们提供一份简单的易于追踪的数据集合,来查找有关行星的数字和情况。一张 HTML 数据表将是理想的,你需要先获得可用的数据,然后把它变成一张表格,跟着下面的步骤。</p> + +<p>完成后的表格看上去应该是这样的:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14609/assessment-table.png" style="display: block; margin: 0 auto;"></p> + +<p>你也可以 <a class="external-icon" href="https://roy-tian.github.io/learning-area/html/tables/assessment-finished/planets-data.html">在线查看</a> (不要偷看源代码,不要作弊哦!)</p> + +<ul> +</ul> + +<h2 id="要完成的步骤">要完成的步骤</h2> + +<p>下面的步骤描述了:为了完成这个示例的表格,你所要做的事情 。所有你需要的数据都包含在<code>planets-data.txt</code> 文件中。如果你在获得这些数据时遇到了问题,也看看上面的实例,或者尝试绘制一个图。</p> + +<ol> + <li>打开在你本地环境中的 <code>blank-template.html</code>副本,提供一个外部容器来初始化表格,一个表格 header,一个表格 body。在这个例子中,你不需要表格 footer 。</li> + <li>为你的表格添加我们提供的标题。</li> + <li>在表格的 header 中添加一行,用来包括所有列的标题。</li> + <li>在表格的 body 部分创建所有内容行,记住要让所有是行标题的单元格语义化。</li> + <li>确保所有内容都插入了正确的单元格,在原始数据中,每行行星数据都显示在其相关行星的旁边。</li> + <li>添加一些属性,让行标题和列标题更加明确地与和它们有关的单元格进行关联,使用 rowgroups 让子标题和父标题也进行关联。</li> + <li>为包含所有行星标题的行标题的那一列数据,添加一个黑色边框</li> +</ol> + +<h2 id="要点和提示">要点和提示</h2> + +<ul> + <li>标题行的第一个单元格需要是空白的,然后宽度为 2 个单元格。</li> + <li>行的主标题 (e.g. <em>Jovian planets</em>) 以及放置在行星名称行左侧的标题 (e.g. <em>Saturn</em>) 整理出来有点麻烦, — 你需要确保每个单元格都有正确的高度和宽度。(即横跨正确的行数和列数)</li> + <li>将标题与其行/列相关联的一种方法比其他方法容易得多。</li> +</ul> + +<h2 id="评定">评定</h2> + +<p>如果您将此评估作为有组织的课程的一部分,您应该能够将您的工作交给您的老师/导师进行评改。 如果您是自学习的,那么您可以通过询问 <a href="https://discourse.mozilla-community.org/t/learning-web-development-marking-guides-and-questions/16294">Learning Area Discourse thread</a>, 或在 <a href="irc://irc.mozilla.org/mdn">#mdn</a>的IRC频道 <a href="https://wiki.mozilla.org/IRC">Mozilla IRC</a> 中轻松获得标记指南. 首先尝试练习 - 作弊对你没有益处!</p> + +<p>{{PreviousMenu("Learn/HTML/Tables/Advanced", "Learn/HTML/Tables")}}</p> |