<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ HTML - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ freeCodeCamp 是一个免费学习编程的开发者社区，涵盖 Python、HTML、CSS、React、Vue、BootStrap、JSON 教程等，还有活跃的技术论坛和丰富的社区活动，在你学习编程和找工作时为你提供建议和帮助。 ]]>
        </description>
        <link>https://www.freecodecamp.org/chinese/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ HTML - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/chinese/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Thu, 21 May 2026 15:49:24 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/chinese/news/tag/html/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ 从零开始实现一个玩具版浏览器渲染引擎 ]]>
                </title>
                <description>
                    <![CDATA[ 浏览器渲染原理作为前端必须要了解的知识点之一，在面试中经常会被问到。在一些前端书籍或者培训课程里也会经常被提及，比如 MDN 文档中就有渲染原理 [https://developer.mozilla.org/zh-CN/docs/Web/Performance/How_browsers_work#%E6%B8%B2%E6%9F%93] 的相关描述。 作为一名工作多年的前端，我对于渲染原理自然也是了解的，但是对于它的理解只停留在理论知识层面。所以我决定自己动手实现一个玩具版的渲染引擎。 渲染引擎是浏览器的一部分，它负责将网页内容（HTML、CSS、JavaScript 等）转化为用户可阅读、观看、听到的形式。但是要独自实现一个完整的渲染引擎工作量实在太大了，而且也很困难。于是我决定退一步，打算实现一个玩具版的渲染引擎。刚好 Github 上有一个开源的用 Rust 写的玩具版渲染引擎 robinson [https://github.com/woai3c/tiny-rendering-engine]，于是决定模仿其源码自己用 JavaScript 实现一遍，并且也在 Github 上 ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/browser-rendering-engine/</link>
                <guid isPermaLink="false">64fed78058a38a1950d360df</guid>
                
                    <category>
                        <![CDATA[ 浏览器 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ HTML ]]>
                    </category>
                
                    <category>
                        <![CDATA[ CSS ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ woai3c ]]>
                </dc:creator>
                <pubDate>Tue, 12 Sep 2023 03:35:00 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2023/09/1694616133719.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>浏览器渲染原理作为前端必须要了解的知识点之一，在面试中经常会被问到。在一些前端书籍或者培训课程里也会经常被提及，比如 MDN 文档中就有<a href="https://developer.mozilla.org/zh-CN/docs/Web/Performance/How_browsers_work#%E6%B8%B2%E6%9F%93">渲染原理</a>的相关描述。</p><p>作为一名工作多年的前端，我对于渲染原理自然也是了解的，但是对于它的理解只停留在理论知识层面。所以我决定自己动手实现一个玩具版的渲染引擎。</p><p>渲染引擎是浏览器的一部分，它负责将网页内容（HTML、CSS、JavaScript 等）转化为用户可阅读、观看、听到的形式。但是要独自实现一个完整的渲染引擎工作量实在太大了，而且也很困难。于是我决定退一步，打算实现一个玩具版的渲染引擎。刚好 Github 上有一个开源的用 Rust 写的玩具版渲染引擎 <a href="https://github.com/woai3c/tiny-rendering-engine">robinson</a>，于是决定模仿其源码自己用 JavaScript 实现一遍，并且也在 Github 上开源了<a href="https://github.com/woai3c/tiny-rendering-engine">从零开始实现一个玩具版浏览器渲染引擎</a>。</p><p>这个玩具版的渲染引擎一共分为五个阶段：</p><figure class="kg-card kg-image-card"><img src="https://pic1.zhimg.com/80/v2-266e8e94510504d11b930612229012ac_1440w.webp" class="kg-image" alt="v2-266e8e94510504d11b930612229012ac_1440w" width="739" height="204" loading="lazy"></figure><p>分别是：</p><ol><li>解析 HTML，生成 DOM 树</li><li>解析 CSS，生成 CSS 规则集合</li><li>生成 Style 树</li><li>生成布局树</li><li>绘制</li></ol><p>每个阶段的代码我在仓库上都用一个分支来表示。由于直接看整个渲染引擎的代码可能会比较困难，所以我建议大家从第一个分支开始进行学习，从易到难，这样学习效果更好。</p><figure class="kg-card kg-image-card"><img src="https://pic3.zhimg.com/80/v2-27a55d7173240190324c2f9d18b02a32_1440w.webp" class="kg-image" alt="v2-27a55d7173240190324c2f9d18b02a32_1440w" width="222" height="152" loading="lazy"></figure><p>现在我们先看一下如何编写一个 HTML 解析器。</p><h3 id="html-">HTML 解析器</h3><p>HTML 解析器的作用就是将一连串的 HTML 文本解析为 DOM 树。比如将这样的 HTML 文本：</p><pre><code class="language-html">&lt;div class="lightblue test" id=" div " data-index="1"&gt;test!&lt;/div&gt;</code></pre><p>解析为一个 DOM 树：</p><pre><code class="language-js">{
    "tagName": "div",
    "attributes": {
        "class": "lightblue test",
        "id": "div",
        "data-index": "1"
    },
    "children": [
        {
            "nodeValue": "test!",
            "nodeType": 3
        }
    ],
    "nodeType": 1
}
</code></pre><p>写解析器需要懂一些编译原理的知识，比如词法分析、语法分析什么的。但是我们的玩具版解析器非常简单，即使不懂也没有关系，大家看源码就能明白了。</p><p>再回到上面的那段 HTML 文本，它的整个解析过程可以用下面的图来表示，每一段 HTML 文本都有对应的方法去解析。</p><figure class="kg-card kg-image-card"><img src="https://pic4.zhimg.com/80/v2-19271cbd4bdf074f13f0351d39415b4f_1440w.webp" class="kg-image" alt="v2-19271cbd4bdf074f13f0351d39415b4f_1440w" width="1223" height="305" loading="lazy"></figure><p>为了让解析器实现起来简单一点，我们需要对 HTML 的功能进行约束：</p><ol><li>标签必须要成对出现：<code>&lt;div&gt;...&lt;/div&gt;</code></li><li>HTML 属性值必须要有引号包起来 <code>&lt;div class="test"&gt;...&lt;/div&gt;</code></li><li>不支持注释</li><li>尽量不做错误处理</li><li>只支持两种类型节点 <code>Element</code> 和 <code>Text</code></li></ol><p>对解析器的功能进行约束后，代码实现就变得简单多了，现在让我们继续吧。</p><h3 id="-">节点类型</h3><p>首先，为这两种节点 <code>Element</code> 和 <code>Text</code> 定一个适当的数据结构：</p><pre><code class="language-ts">export enum NodeType {
    Element = 1,
    Text = 3,
}

export interface Element {
    tagName: string
    attributes: Record&lt;string, string&gt;
    children: Node[]
    nodeType: NodeType.Element
}

interface Text {
    nodeValue: string
    nodeType: NodeType.Text
}

export type Node = Element | Text
</code></pre><p>然后为这两种节点各写一个生成函数：</p><pre><code class="language-ts">export function element(tagName: string) {
    return {
        tagName,
        attributes: {},
        children: [],
        nodeType: NodeType.Element,
    } as Element
}

export function text(data: string) {
    return {
        nodeValue: data,
        nodeType: NodeType.Text,
    } as Text
}
</code></pre><p>这两个函数在解析到元素节点或者文本节点时调用，调用后会返回对应的 DOM 节点。</p><h3 id="html--1">HTML 解析器的执行过程</h3><p>下面这张图就是整个 HTML 解析器的执行过程：</p><figure class="kg-card kg-image-card"><img src="https://pic3.zhimg.com/80/v2-5fc6cad8bfec2129f8f1c82cb71175a2_1440w.webp" class="kg-image" alt="v2-5fc6cad8bfec2129f8f1c82cb71175a2_1440w" width="987" height="638" loading="lazy"></figure><p>HTML 解析器的入口方法为 <code>parse()</code>，从这开始执行直到遍历完所有 HTML 文本为止：</p><ol><li>判断当前字符是否为 <code>&lt;</code>，如果是，则当作元素节点来解析，调用 <code>parseElement()</code>，否则调用 <code>parseText()</code></li><li><code>parseText()</code> 比较简单，一直往前遍历字符串，直至遇到 <code>&lt;</code> 字符为止。然后将之前遍历过的所有字符当作 <code>Text</code> 节点的值。</li><li><code>parseElement()</code> 则相对复杂一点，它首先要解析出当前的元素标签名称，这段文本用 <code>parseTag()</code> 来解析。</li><li>然后再进入 <code>parseAttrs()</code> 方法，判断是否有属性节点，如果该节点有 <code>class</code> 或者其他 HTML 属性，则会调用 <code>parseAttr()</code> 把 HTML 属性或者 <code>class</code> 解析出来。</li><li>至此，整个元素节点的前半段已经解析完了。接下来需要解析它的子节点。这时就会进入无限递归循环回到第一步，继续解析元素节点或文本节点。</li><li>当所有子节点解析完后，需要调用 <code>parseTag()</code>，看看结束标签名和元素节点的开始标签名是否相同，如果相同，则 <code>parseElement()</code> 或者 <code>parse()</code> 结束，否则报错。</li></ol><h3 id="html--2">HTML 解析器各个方法详解</h3><h3 id="-parse-">入口方法 parse()</h3><p>HTML 的入口方法是 <code>parse(rawText)</code></p><pre><code class="language-ts">parse(rawText: string) {
    this.rawText = rawText.trim()
    this.len = this.rawText.length
    this.index = 0
    this.stack = []

    const root = element('root')
    while (this.index &lt; this.len) {
        this.removeSpaces()
        if (this.rawText[this.index].startsWith('&lt;')) {
            this.index++
            this.parseElement(root)
        } else {
            this.parseText(root)
        }
    }
}
</code></pre><p>入口方法需要遍历所有文本，在一开始它需要判断当前字符是否是 <code>&lt;</code>，如果是，则将它当作元素节点来解析，调用 <code>parseElement()</code>，否则将当前字符作为文本来解析，调用 <code>parseText()</code>。</p><h3 id="-parseelement-">解析元素节点 <code>parseElement()</code></h3><pre><code class="language-ts">private parseElement(parent: Element) {
 // 解析标签
    const tag = this.parseTag()
    // 生成元素节点
    const ele = element(tag)

    this.stack.push(tag)

    parent.children.push(ele)
    // 解析属性
    this.parseAttrs(ele)

    while (this.index &lt; this.len) {
        this.removeSpaces()
        if (this.rawText[this.index].startsWith('&lt;')) {
            this.index++
            this.removeSpaces()
            // 判断是否是结束标签
            if (this.rawText[this.index].startsWith('/')) {
                this.index++
                const startTag = this.stack[this.stack.length - 1]
                // 结束标签
                const endTag = this.parseTag()
                if (startTag !== endTag) {
                    throw Error(`The end tagName ${endTag} does not match start tagName ${startTag}`)
                }

                this.stack.pop()
                while (this.index &lt; this.len &amp;&amp; this.rawText[this.index] !== '&gt;') {
                    this.index++
                }

                break
            } else {
                this.parseElement(ele)
            }
        } else {
            this.parseText(ele)
        }
    }

    this.index++
}
</code></pre><p><code>parseElement()</code> 会依次调用 <code>parseTag()</code> <code>parseAttrs()</code> 解析标签和属性，然后再递归解析子节点，终止条件是遍历完所有的 HTML 文本。</p><h3 id="-parsetext-">解析文本节点 <code>parseText()</code></h3><pre><code class="language-ts">private parseText(parent: Element) {
    let str = ''
    while (
        this.index &lt; this.len
        &amp;&amp; !(this.rawText[this.index] === '&lt;' &amp;&amp; /\w|\//.test(this.rawText[this.index + 1]))
    ) {
        str += this.rawText[this.index]
        this.index++
    }

    this.sliceText()
    parent.children.push(text(removeExtraSpaces(str)))
}
</code></pre><p>解析文本相对简单一点，它会一直往前遍历，直至遇到 <code>&lt;</code> 为止。比如这段文本 <code>&lt;div&gt;test!&lt;/div&gt;</code>，经过 <code>parseText()</code> 解析后拿到的文本是 <code>test!</code>。</p><h3 id="-parsetag-">解析标签 <code>parseTag()</code></h3><p>在进入 <code>parseElement()</code> 后，首先调用就是 <code>parseTag()</code>，它的作用是解析标签名：</p><pre><code class="language-ts">private parseTag() {
    let tag = ''

    this.removeSpaces()

    // get tag name
    while (this.index &lt; this.len &amp;&amp; this.rawText[this.index] !== ' ' &amp;&amp; this.rawText[this.index] !== '&gt;') {
        tag += this.rawText[this.index]
        this.index++
    }

    this.sliceText()
    return tag
}
</code></pre><p>比如这段文本 <code>&lt;div&gt;test!&lt;/div&gt;</code>，经过 <code>parseTag()</code> 解析后拿到的标签名是 <code>div</code>。</p><h3 id="-parseattrs-">解析属性节点 <code>parseAttrs()</code></h3><p>解析完标签名后，接着再解析属性节点：</p><pre><code class="language-ts">// 解析元素节点的所有属性
private parseAttrs(ele: Element) {
 // 一直遍历文本，直至遇到 '&gt;' 字符为止，代表 &lt;div ....&gt; 这一段文本已经解析完了
    while (this.index &lt; this.len &amp;&amp; this.rawText[this.index] !== '&gt;') {
        this.removeSpaces()
        this.parseAttr(ele)
        this.removeSpaces()
    }

    this.index++
}

// 解析单个属性，例如 class="foo bar"
private parseAttr(ele: Element) {
    let attr = ''
    let value = ''
    while (this.index &lt; this.len &amp;&amp; this.rawText[this.index] !== '=' &amp;&amp; this.rawText[this.index] !== '&gt;') {
        attr += this.rawText[this.index++]
    }

    this.sliceText()
    attr = attr.trim()
    if (!attr.trim()) return

    this.index++
    let startSymbol = ''
    if (this.rawText[this.index] === "'" || this.rawText[this.index] === '"') {
        startSymbol = this.rawText[this.index++]
    }

    while (this.index &lt; this.len &amp;&amp; this.rawText[this.index] !== startSymbol) {
        value += this.rawText[this.index++]
    }

    this.index++
    ele.attributes[attr] = value.trim()
    this.sliceText()
}
</code></pre><p><code>parseAttr()</code> 可以将这样的文本 <code>class="test"</code> 解析为一个对象 <code>{ class: "test" }</code>。</p><h3 id="--1">其他辅助方法</h3><p>有时不同的节点、属性之间有很多多余的空格，所以需要写一个方法将多余的空格清除掉。</p><pre><code class="language-ts">protected removeSpaces() {
    while (this.index &lt; this.len &amp;&amp; (this.rawText[this.index] === ' ' || this.rawText[this.index] === '\n')) {
        this.index++
    }

    this.sliceText()
}
</code></pre><p>同时为了方便调试，开发者经常需要打断点看当前正在遍历的字符是什么。如果以前遍历过的字符串还在，那么是比较难调试的，因为开发者需要根据 index 的值自己去找当前遍历的字符是什么。所以所有解析完的 HTML 文本，都需要截取掉，确保当前的 HTML 文本都是没有被遍历：</p><pre><code class="language-ts">protected sliceText() {
    this.rawText = this.rawText.slice(this.index)
    this.len = this.rawText.length
    this.index = 0
}
</code></pre><p><code>sliceText()</code> 方法的作用就是截取已经遍历过的 HTML 文本。用下图来做例子，假设当前要解析 <code>div</code> 这个标签名：</p><figure class="kg-card kg-image-card"><img src="https://pic2.zhimg.com/80/v2-d18d74c75c7c028b686132e9c2377b9d_1440w.webp" class="kg-image" alt="v2-d18d74c75c7c028b686132e9c2377b9d_1440w" width="1169" height="301" loading="lazy"></figure><p>那么解析后需要对 HTML 文本进行截取，就像下图这样：</p><figure class="kg-card kg-image-card"><img src="https://pic2.zhimg.com/80/v2-8a073dda6507fcb4e834339399065ba5_1440w.webp" class="kg-image" alt="v2-8a073dda6507fcb4e834339399065ba5_1440w" width="923" height="179" loading="lazy"></figure><h3 id="--2">小结</h3><p>至此，整个 HTML 解析器的逻辑已经讲完了，所有代码加起来 200 行左右，如果不算 TS 各种类型声明，代码只有 100 多行。</p><h3 id="css-">CSS 解析器</h3><p>CSS 样式表是一系列的 CSS 规则集合，而 CSS 解析器的作用就是将 CSS 文本解析为 CSS 规则集合。</p><pre><code class="language-css">div, p {
    font-size: 88px;
    color: #000;
}</code></pre><p>例如上面的 CSS 文本，经过解析器解析后，会生成下面的 CSS 规则集合：</p><pre><code class="language-js">[
    {
        "selectors": [
            {
                "id": "",
                "class": "",
                "tagName": "div"
            },
            {
                "id": "",
                "class": "",
                "tagName": "p"
            }
        ],
        "declarations": [
            {
                "name": "font-size",
                "value": "88px"
            },
            {
                "name": "color",
                "value": "#000"
            }
        ]
    }
]
</code></pre><p>每个规则都有一个 <code>selector</code> 和 <code>declarations</code> 属性，其中 <code>selectors</code> 表示 CSS 选择器，<code>declarations</code> 表示 CSS 的属性描述集合。</p><pre><code class="language-ts">export interface Rule {
    selectors: Selector[]
    declarations: Declaration[]
}

export interface Selector {
    tagName: string
    id: string
    class: string
}

export interface Declaration {
    name: string
    value: string | number
}
</code></pre><figure class="kg-card kg-image-card"><img src="https://pic4.zhimg.com/80/v2-4ae9e0e860a5248e0e4e3a82f2c983eb_1440w.webp" class="kg-image" alt="v2-4ae9e0e860a5248e0e4e3a82f2c983eb_1440w" width="758" height="267" loading="lazy"></figure><p>每一条 CSS 规则都可以包含多个选择器和多个 CSS 属性。</p><h3 id="-css-parserule-">解析 CSS 规则 <code>parseRule()</code></h3><pre><code class="language-ts">private parseRule() {
    const rule: Rule = {
        selectors: [],
        declarations: [],
    }

    rule.selectors = this.parseSelectors()
    rule.declarations = this.parseDeclarations()

    return rule
}
</code></pre><p>在 <code>parseRule()</code> 里，它分别调用了 <code>parseSelectors()</code> 去解析 CSS 选择器，然后再对剩余的 CSS 文本执行 <code>parseDeclarations()</code> 去解析 CSS 属性。</p><h3 id="-parseselector-">解析选择器 <code>parseSelector()</code></h3><pre><code class="language-ts">private parseSelector() {
    const selector: Selector = {
        id: '',
        class: '',
        tagName: '',
    }

    switch (this.rawText[this.index]) {
        case '.':
            this.index++
            selector.class = this.parseIdentifier()
            break
        case '#':
            this.index++
            selector.id = this.parseIdentifier()
            break
        case '*':
            this.index++
            selector.tagName = '*'
            break
        default:
            selector.tagName = this.parseIdentifier()
    }

    return selector
}

private parseIdentifier() {
    let result = ''
    while (this.index &lt; this.len &amp;&amp; this.identifierRE.test(this.rawText[this.index])) {
        result += this.rawText[this.index++]
    }

    this.sliceText()
    return result
}
</code></pre><p>选择器我们只支持标签名称、前缀为 <code>#</code> 的 ID 、前缀为任意数量的类名 <code>.</code> 或上述的某种组合。如果标签名称为 <code>*</code>，则表示它是一个通用选择器，可以匹配任何标签。</p><p>标准的 CSS 解析器在遇到无法识别的部分时，会将它丢掉，然后继续解析其余部分。主要是为了兼容旧浏览器和防止发生错误导致程序中断。我们的 CSS 解析器为了实现简单，没有做这方面的做错误处理。</p><h3 id="-css-parsedeclaration-">解析 CSS 属性 <code>parseDeclaration()</code></h3><pre><code class="language-ts">private parseDeclaration() {
    const declaration: Declaration = { name: '', value: '' }
    this.removeSpaces()
    declaration.name = this.parseIdentifier()
    this.removeSpaces()

    while (this.index &lt; this.len &amp;&amp; this.rawText[this.index] !== ':') {
        this.index++
    }

    this.index++ // clear :
    this.removeSpaces()
    declaration.value = this.parseValue()
    this.removeSpaces()

    return declaration
}
</code></pre><p><code>parseDeclaration()</code> 会将 <code>color: red;</code> 解析为一个对象 <code>{ name: "color", value: "red" }</code>。</p><h3 id="--3">小结</h3><p>CSS 解析器相对来说简单多了，因为很多知识点在 HTML 解析器中已经讲到。整个 CSS 解析器的代码大概 100 多行，如果你阅读过 HTML 解析器的源码，相信看 CSS 解析器的源码会更轻松。</p><h3 id="--4">构建样式树</h3><p>本阶段的目标是写一个样式构建器，输入 DOM 树和 CSS 规则集合，生成一棵样式树 Style tree。</p><figure class="kg-card kg-image-card"><img src="https://pic1.zhimg.com/80/v2-266e8e94510504d11b930612229012ac_1440w.webp" class="kg-image" alt="v2-266e8e94510504d11b930612229012ac_1440w" width="739" height="204" loading="lazy"></figure><p>样式树的每一个节点都包含了 CSS 属性值以及它对应的 DOM 节点引用：</p><pre><code class="language-ts">interface AnyObject {
    [key: string]: any
}

export interface StyleNode {
    node: Node // DOM 节点
    values: AnyObject // style 属性值
    children: StyleNode[] // style 子节点
}
</code></pre><p>先来看一个简单的示例：</p><pre><code class="language-html">&lt;div&gt;test&lt;/div&gt;
div {
    font-size: 88px;
    color: #000;
}</code></pre><p>上述的 HTML、CSS 文本在经过样式树构建器处理后生成的样式树如下：</p><pre><code class="language-js">{
    "node": { // DOM 节点
        "tagName": "div",
        "attributes": {},
        "children": [
            {
                "nodeValue": "test",
                "nodeType": 3
            }
        ],
        "nodeType": 1
    },
    "values": { // CSS 属性值
        "font-size": "88px",
        "color": "#000"
    },
    "children": [ // style tree 子节点
        {
            "node": {
                "nodeValue": "test",
                "nodeType": 3
            },
            "values": { // text 节点继承了父节点样式
                "font-size": "88px",
                "color": "#000"
            },
            "children": []
        }
    ]
}
</code></pre><h3 id="-dom-">遍历 DOM 树</h3><p>现在我们需要遍历 DOM 树。对于 DOM 树中的每个节点，我们都要在样式树中查找是否有匹配的 CSS 规则。</p><pre><code class="language-ts">export function getStyleTree(eles: Node | Node[], cssRules: Rule[], parent?: StyleNode) {
    if (Array.isArray(eles)) {
        return eles.map((ele) =&gt; getStyleNode(ele, cssRules, parent))
    }

    return getStyleNode(eles, cssRules, parent)
}
</code></pre><h3 id="--5">匹配选择器</h3><p>匹配选择器实现起来非常容易，因为我们的CSS 解析器仅支持简单的选择器。 只需要查看元素本身即可判断选择器是否与元素匹配。</p><pre><code class="language-ts">/**
 * css 选择器是否匹配元素
 */
function isMatch(ele: Element, selectors: Selector[]) {
    return selectors.some((selector) =&gt; {
        // 通配符
        if (selector.tagName === '*') return true
        if (selector.tagName === ele.tagName) return true
        if (ele.attributes.id === selector.id) return true

        if (ele.attributes.class) {
            const classes = ele.attributes.class.split(' ').filter(Boolean)
            const classes2 = selector.class.split(' ').filter(Boolean)
            for (const name of classes) {
                if (classes2.includes(name)) return true
            }
        }

        return false
    })
}
</code></pre><p>当查找到匹配的 DOM 节点后，再将 DOM 节点和它匹配的 CSS 属性组合在一起，生成样式树节点 styleNode：</p><pre><code class="language-ts">function getStyleNode(ele: Node, cssRules: Rule[], parent?: StyleNode) {
    const styleNode: StyleNode = {
        node: ele,
        values: getStyleValues(ele, cssRules, parent),
        children: [],
    }

    if (ele.nodeType === NodeType.Element) {
        // 合并内联样式
        if (ele.attributes.style) {
            styleNode.values = { ...styleNode.values, ...getInlineStyle(ele.attributes.style) }
        }

        styleNode.children = ele.children.map((e) =&gt; getStyleNode(e, cssRules, styleNode)) as unknown as StyleNode[]
    }

    return styleNode
}

function getStyleValues(ele: Node, cssRules: Rule[], parent?: StyleNode) {
    const inheritableAttrValue = getInheritableAttrValues(parent)

    // 文本节点继承父元素的可继承属性
    if (ele.nodeType === NodeType.Text) return inheritableAttrValue

    return cssRules.reduce((result: AnyObject, rule) =&gt; {
        if (isMatch(ele as Element, rule.selectors)) {
            result = { ...result, ...cssValueArrToObject(rule.declarations) }
        }

        return result
    }, inheritableAttrValue)
}
</code></pre><p>在 CSS 选择器中，不同的选择器优先级是不同的，比如 id 选择器就比类选择器的优先级要高。但是我们这里没有实现选择器优先级，为了实现简单，所有的选择器优先级是一样的。</p><h3 id="--6">继承属性</h3><p>文本节点无法匹配选择器，那它的样式从哪来？答案就是继承，它可以继承父节点的样式。</p><p>在 CSS 中存在很多继承属性，即使子元素没有声明这些属性，也可以从父节点里继承。比如字体颜色、字体家族等属性，都是可以被继承的。为了实现简单，这里只支持继承父节点的 <code>color</code>、<code>font-size</code> 属性。</p><pre><code class="language-ts">// 子元素可继承的属性，这里只写了两个，实际上还有很多
const inheritableAttrs = ['color', 'font-size']

/**
 * 获取父元素可继承的属性值
 */
function getInheritableAttrValues(parent?: StyleNode) {
    if (!parent) return {}
    const keys = Object.keys(parent.values)
    return keys.reduce((result: AnyObject, key) =&gt; {
        if (inheritableAttrs.includes(key)) {
            result[key] = parent.values[key]
        }

        return result
    }, {})
}
</code></pre><h3 id="--7">内联样式</h3><p>在 CSS 中，内联样式的优先级是除了 <code>!important</code> 之外最高的。</p><pre><code class="language-html">&lt;span style="color: red; background: yellow;"&gt;</code></pre><p>我们可以在调用 <code>getStyleValues()</code> 函数获得当前 DOM 节点的 CSS 属性值后，再去取当前节点的内联样式值。并对当前 DOM 节点的 CSS 样式值进行覆盖。</p><pre><code class="language-ts">styleNode.values = { ...styleNode.values, ...getInlineStyle(ele.attributes.style) }

function getInlineStyle(str: string) {
    str = str.trim()
    if (!str) return {}
    const arr = str.split(';')
    if (!arr.length) return {}

    return arr.reduce((result: AnyObject, item: string) =&gt; {
        const data = item.split(':')
        if (data.length === 2) {
            result[data[0].trim()] = data[1].trim()
        }

        return result
    }, {})
}
</code></pre><h3 id="--8">布局树</h3><p>第四阶段讲的是如何将样式树转化为布局树，也是整个渲染引擎相对比较复杂的部分。</p><figure class="kg-card kg-image-card"><img src="https://pic1.zhimg.com/80/v2-266e8e94510504d11b930612229012ac_1440w.webp" class="kg-image" alt="v2-266e8e94510504d11b930612229012ac_1440w" width="739" height="204" loading="lazy"></figure><h3 id="css--1">CSS 盒子模型</h3><p>在 CSS 中，所有的 DOM 节点都可以当作一个盒子。这个盒子模型包含了内容、内边距、边框、外边距以及在页面中的位置信息。</p><figure class="kg-card kg-image-card"><img src="https://pic3.zhimg.com/80/v2-6ca1a4d0cb14b09aea28fefe3dc91dc2_1440w.webp" class="kg-image" alt="v2-6ca1a4d0cb14b09aea28fefe3dc91dc2_1440w" width="494" height="341" loading="lazy"></figure><p>我们可以用以下的数据结构来表示盒子模型：</p><pre><code class="language-ts">export default class Dimensions {
    content: Rect
    padding: EdgeSizes
    border: EdgeSizes
    margin: EdgeSizes
}

export default class Rect {
    x: number
    y: number
    width: number
    height: number
}

export interface EdgeSizes {
    top: number
    right: number
    bottom: number
    left: number
}
</code></pre><h3 id="--9">块布局和内联布局</h3><p>CSS 的 <code>display</code> 属性决定了盒子在页面中的布局方式。<code>display</code> 的类型有很多种，例如 <code>block</code>、<code>inline</code>、<code>flex</code> 等等，但这里只支持 <code>block</code> 和 <code>inline</code> 两种布局方式，并且所有盒子的默认布局方式为 <code>display: inline</code>。</p><p>我会用伪 HTML 代码来描述它们之间的区别：</p><pre><code class="language-html">&lt;container&gt;
  &lt;a&gt;&lt;/a&gt;
  &lt;b&gt;&lt;/b&gt;
  &lt;c&gt;&lt;/c&gt;
  &lt;d&gt;&lt;/d&gt;
&lt;/container&gt;</code></pre><p>块布局会将盒子从上至下的垂直排列。</p><figure class="kg-card kg-image-card"><img src="https://pic3.zhimg.com/80/v2-02572058706b774cb4eb6d2920127b6a_1440w.webp" class="kg-image" alt="v2-02572058706b774cb4eb6d2920127b6a_1440w" width="384" height="224" loading="lazy"></figure><p>内联布局则会将盒子从左至右的水平排列。</p><figure class="kg-card kg-image-card"><img src="https://pic3.zhimg.com/80/v2-dbd175cba44b114a7a8fe74efac00b7a_1440w.webp" class="kg-image" alt="v2-dbd175cba44b114a7a8fe74efac00b7a_1440w" width="393" height="130" loading="lazy"></figure><p>如果容器内同时存在块布局和内联布局，则会用一个匿名布局将内联布局包裹起来。</p><figure class="kg-card kg-image-card"><img src="https://pic3.zhimg.com/80/v2-98271cb522c63a126d86abfd9648ed8e_1440w.webp" class="kg-image" alt="v2-98271cb522c63a126d86abfd9648ed8e_1440w" width="388" height="236" loading="lazy"></figure><p>这样就能将内联布局的盒子和其他块布局的盒子区别开来。</p><p>通常情况下内容是垂直增长的。也就是说，在容器中添加子节点通常会使容器更高，而不是更宽。另一种说法是，默认情况下，子节点的宽度取决于其容器的宽度，而容器的高度取决于其子节点的高度。</p><h3 id="--10">布局树</h3><p>布局树是所有盒子节点的集合。</p><pre><code class="language-ts">export default class LayoutBox {
 dimensions: Dimensions
 boxType: BoxType
 children: LayoutBox[]
 styleNode: StyleNode
}
</code></pre><p>盒子节点的类型可以是 <code>block</code>、<code>inilne</code> 和 <code>anonymous</code>。</p><pre><code class="language-ts">export enum BoxType {
    BlockNode = 'BlockNode',
    InlineNode = 'InlineNode',
    AnonymousBlock = 'AnonymousBlock',
}
</code></pre><p>我们构建样式树时，需要根据每一个 DOM 节点的 <code>display</code> 属性来生成对应的盒子节点。</p><pre><code class="language-ts">export function getDisplayValue(styleNode: StyleNode) {
    return styleNode.values?.display ?? Display.Inline
}
</code></pre><p>如果 DOM 节点 <code>display</code> 属性的值为 <code>none</code>，则在构建布局树的过程中，无需将这个 DOM 节点添加到布局树上，直接忽略它就可以了。</p><p>如果一个块节点包含一个内联子节点，则需要创建一个匿名块（实际上就是块节点）来包含它。如果一行中有多个子节点，则将它们全部放在同一个匿名容器中。</p><pre><code class="language-ts">function buildLayoutTree(styleNode: StyleNode) {
    if (getDisplayValue(styleNode) === Display.None) {
        throw new Error('Root node has display: none.')
    }

    const layoutBox = new LayoutBox(styleNode)

    let anonymousBlock: LayoutBox | undefined
    for (const child of styleNode.children) {
        const childDisplay = getDisplayValue(child)
        // 如果 DOM 节点 display 属性值为 none，直接跳过
        if (childDisplay === Display.None) continue

        if (childDisplay === Display.Block) {
            anonymousBlock = undefined
            layoutBox.children.push(buildLayoutTree(child))
        } else {
         // 创建一个匿名容器，用于容纳内联节点
            if (!anonymousBlock) {
                anonymousBlock = new LayoutBox()
                layoutBox.children.push(anonymousBlock)
            }

            anonymousBlock.children.push(buildLayoutTree(child))
        }
    }

    return layoutBox
}
</code></pre><h3 id="--11">遍历布局树</h3><p>现在开始构建布局树，入口函数是 <code>getLayoutTree()</code>：</p><pre><code class="language-ts">export function getLayoutTree(styleNode: StyleNode, parentBlock: Dimensions) {
    parentBlock.content.height = 0
    const root = buildLayoutTree(styleNode)
    root.layout(parentBlock)
    return root
}
</code></pre><p>它将遍历样式树，利用样式树节点提供的相关信息，生成一个 <code>LayoutBox</code> 对象，然后调用 <code>layout()</code> 方法。计算每个盒子节点的位置、尺寸信息。</p><p>在本节内容的开头有提到过，盒子的宽度取决于其父节点，而高度取决于子节点。这意味着，我们的代码在计算宽度时需要自上而下遍历树，这样它就可以在知道父节点的宽度后设置子节点的宽度。然后自下而上遍历以计算高度，这样父节点的高度就可以在计算子节点的相关信息后进行计算。</p><pre><code class="language-ts">layout(parentBlock: Dimensions) {
 // 子节点的宽度依赖于父节点的宽度，所以要先计算当前节点的宽度，再遍历子节点
    this.calculateBlockWidth(parentBlock)
    // 计算盒子节点的位置
    this.calculateBlockPosition(parentBlock)
    // 遍历子节点并计算对位置、尺寸信息
    this.layoutBlockChildren()
    // 父节点的高度依赖于其子节点的高度，所以计算子节点的高度后，再计算自己的高度
    this.calculateBlockHeight()
}
</code></pre><p>这个方法执行布局树的单次遍历，向下执行宽度计算，向上执行高度计算。一个真正的布局引擎可能会执行几次树遍历，有些是自上而下的，有些是自下而上的。</p><h3 id="--12">计算宽度</h3><p>现在，我们先来计算盒子节点的宽度，这部分比较复杂，需要详细的讲解。</p><p>首先，我们要拿到当前节点的 <code>width</code> <code>padding</code> <code>border</code> <code>margin</code> 等信息：</p><pre><code class="language-ts">calculateBlockWidth(parentBlock: Dimensions) {
 // 初始值
 const styleValues = this.styleNode?.values || {}

 // 初始值为 auto
 let width = styleValues.width ?? 'auto'
 let marginLeft = styleValues['margin-left'] || styleValues.margin || 0
 let marginRight = styleValues['margin-right'] || styleValues.margin || 0

 let borderLeft = styleValues['border-left'] || styleValues.border || 0
 let borderRight = styleValues['border-right'] || styleValues.border || 0

 let paddingLeft = styleValues['padding-left'] || styleValues.padding || 0
 let paddingRight = styleValues['padding-right'] || styleValues.padding || 0

 // 拿到父节点的宽度，如果某个属性为 'auto'，则将它设为 0
 let totalWidth = sum(width, marginLeft, marginRight, borderLeft, borderRight, paddingLeft, paddingRight)
 // ...
</code></pre><p>如果这些属性没有设置，就使用 0 作为默认值。拿到当前节点的总宽度后，还需要和父节点对比一下是否相等。如果宽度或边距设置为 <code>auto</code>，则可以对这两个属性进行适当展开或收缩以适应可用空间。所以现在需要对当前节点的宽度进行检查。</p><pre><code class="language-ts">const isWidthAuto = width === 'auto'
const isMarginLeftAuto = marginLeft === 'auto'
const isMarginRightAuto = marginRight === 'auto'

// 当前块的宽度如果超过了父元素宽度，则将它的可扩展外边距设为 0
if (!isWidthAuto &amp;&amp; totalWidth &gt; parentWidth) {
    if (isMarginLeftAuto) {
        marginLeft = 0
    }

    if (isMarginRightAuto) {
        marginRight = 0
    }
}

// 根据父子元素宽度的差值，去调整当前元素的宽度
const underflow = parentWidth - totalWidth

// 如果三者都有值，则将差值填充到 marginRight
if (!isWidthAuto &amp;&amp; !isMarginLeftAuto &amp;&amp; !isMarginRightAuto) {
    marginRight += underflow
} else if (!isWidthAuto &amp;&amp; !isMarginLeftAuto &amp;&amp; isMarginRightAuto) {
 // 如果右边距是 auto，则将 marginRight 设为差值
    marginRight = underflow
} else if (!isWidthAuto &amp;&amp; isMarginLeftAuto &amp;&amp; !isMarginRightAuto) {
 // 如果左边距是 auto，则将 marginLeft 设为差值
    marginLeft = underflow
} else if (isWidthAuto) {
    // 如果只有 width 是 auto，则将另外两个值设为 0
    if (isMarginLeftAuto) {
        marginLeft = 0
    }

    if (isMarginRightAuto) {
        marginRight = 0
    }

    if (underflow &gt;= 0) {
        // 展开宽度，填充剩余空间，原来的宽度是 auto，作为 0 来计算的
        width = underflow
    } else {
        // 宽度不能为负数，所以需要调整 marginRight 来代替
        width = 0
        // underflow 为负数，相加实际上就是缩小当前节点的宽度
        marginRight += underflow
    }
} else if (!isWidthAuto &amp;&amp; isMarginLeftAuto &amp;&amp; isMarginRightAuto) {
    // 如果只有 marginLeft 和 marginRight 是 auto，则将两者设为 underflow 的一半
    marginLeft = underflow / 2
    marginRight = underflow / 2
}
</code></pre><p>详细的计算过程请看上述代码，重要的地方都已经标上注释了。</p><p>通过对比当前节点和父节点的宽度，我们可以拿到一个差值：</p><pre><code class="language-ts">// 根据父子元素宽度的差值，去调整当前元素的宽度
const underflow = parentWidth - totalWidth
</code></pre><p>如果这个差值为正数，说明子节点宽度小于父节点；如果差值为负数，说明子节点大于父节。上面这段代码逻辑其实就是根据 <code>underflow</code> <code>width</code> <code>padding</code> <code>margin</code> 等值对子节点的宽度、边距进行调整，以适应父节点的宽度。</p><h3 id="--13">定位</h3><p>计算当前节点的位置相对来说简单一点。这个方法会根据当前节点的 <code>margin</code> <code>border</code> <code>padding</code> 样式以及父节点的位置信息对当前节点进行定位：</p><pre><code class="language-ts">calculateBlockPosition(parentBlock: Dimensions) {
 const styleValues = this.styleNode?.values || {}
 const { x, y, height } = parentBlock.content
 const dimensions = this.dimensions

 dimensions.margin.top = transformValueSafe(styleValues['margin-top'] || styleValues.margin || 0)
 dimensions.margin.bottom = transformValueSafe(styleValues['margin-bottom'] || styleValues.margin || 0)

 dimensions.border.top = transformValueSafe(styleValues['border-top'] || styleValues.border || 0)
 dimensions.border.bottom = transformValueSafe(styleValues['border-bottom'] || styleValues.border || 0)

 dimensions.padding.top = transformValueSafe(styleValues['padding-top'] || styleValues.padding || 0)
 dimensions.padding.bottom = transformValueSafe(styleValues['padding-bottom'] || styleValues.padding || 0)

 dimensions.content.x = x + dimensions.margin.left + dimensions.border.left + dimensions.padding.left
 dimensions.content.y = y + height + dimensions.margin.top + dimensions.border.top + dimensions.padding.top
}

function transformValueSafe(val: number | string) {
    if (val === 'auto') return 0
    return parseInt(String(val))
}
</code></pre><p>比如获取当前节点内容区域的 x 坐标，计算方式如下：</p><pre><code class="language-ts">dimensions.content.x = x + dimensions.margin.left + dimensions.border.left + dimensions.padding.left
</code></pre><figure class="kg-card kg-image-card"><img src="https://pic2.zhimg.com/80/v2-23cf320afb0d12b4b25079d4d1a57805_1440w.webp" class="kg-image" alt="v2-23cf320afb0d12b4b25079d4d1a57805_1440w" width="1140" height="603" loading="lazy"></figure><h3 id="--14">遍历子节点</h3><p>在计算高度之前，需要先遍历子节点，因为父节点的高度需要根据它下面子节点的高度进行适配。</p><pre><code class="language-ts">layoutBlockChildren() {
    const { dimensions } = this
    for (const child of this.children) {
        child.layout(dimensions)
        // 遍历子节点后，再计算父节点的高度
        dimensions.content.height += child.dimensions.marginBox().height
    }
}
</code></pre><p>每个节点的高度就是它上下两个外边距之间的差值，所以可以通过 <code>marginBox()</code> 获得高度：</p><pre><code class="language-ts">export default class Dimensions {
    content: Rect
    padding: EdgeSizes
    border: EdgeSizes
    margin: EdgeSizes

    constructor() {
        const initValue = {
            top: 0,
            right: 0,
            bottom: 0,
            left: 0,
        }

        this.content = new Rect()

        this.padding = { ...initValue }
        this.border = { ...initValue }
        this.margin = { ...initValue }
    }

    paddingBox() {
        return this.content.expandedBy(this.padding)
    }

    borderBox() {
        return this.paddingBox().expandedBy(this.border)
    }

    marginBox() {
        return this.borderBox().expandedBy(this.margin)
    }
}
export default class Rect {
    x: number
    y: number
    width: number
    height: number

    constructor() {
        this.x = 0
        this.y = 0
        this.width = 0
        this.height = 0
    }

    expandedBy(edge: EdgeSizes) {
        const rect = new Rect()
        rect.x = this.x - edge.left
        rect.y = this.y - edge.top
        rect.width = this.width + edge.left + edge.right
        rect.height = this.height + edge.top + edge.bottom

        return rect
    }
}
</code></pre><p>遍历子节点并执行完相关计算方法后，再将各个子节点的高度进行相加，得到父节点的高度。</p><h3 id="height-">height 属性</h3><p>默认情况下，节点的高度等于其内容的高度。但如果手动设置了 <code>height</code> 属性，则需要将节点的高度设为指定的高度：</p><pre><code class="language-ts">calculateBlockHeight() {
    // 如果元素设置了 height，则使用 height，否则使用 layoutBlockChildren() 计算出来的高度
    const height = this.styleNode?.values.height
    if (height) {
        this.dimensions.content.height = parseInt(height)
    }
}
</code></pre><p>为了简单起见，我们不需要实现<a href="https://link.zhihu.com/?target=https%3A//developer.mozilla.org/zh-CN/docs/Web/CSS/CSS_box_model/Mastering_margin_collapsing" rel="nofollow noreferrer">外边距折叠</a>。</p><h3 id="--15">小结</h3><p>布局树是渲染引擎最复杂的部分，这一阶段结束后，我们就了解了布局树中每个盒子节点在页面中的具体位置和尺寸信息。下一步，就是如何把布局树渲染到页面上了。</p><h3 id="--16">绘制</h3><p>绘制阶段主要是根据布局树中各个节点的位置、尺寸信息将它们绘制到页面。目前大多数计算机使用光栅（raster，也称为位图）显示技术。将布局树各个节点绘制到页面的这个过程也被称为“光栅化”。</p><p>浏览器通常在图形API和库（如Skia、Cairo、Direct2D等）的帮助下实现光栅化。这些API提供绘制多边形、直线、曲线、渐变和文本的功能。</p><p>实际上绘制才是最难的部分，但是这一步我们有现成的 <a href="https://link.zhihu.com/?target=https%3A//github.com/Automattic/node-canvas" rel="nofollow noreferrer">canvas</a> 库可以用，不用自己实现一个光栅器，所以相对来说就变得简单了。在真正开始绘制阶段之前，我们先来学习一些关于计算机如何绘制图像、文本的基础知识，有助于我们理解光栅化的具体实现过程。</p><h3 id="--17">计算机如何绘制图像、文本</h3><p>在计算机底层进行像素绘制属于硬件操作，它依赖于屏幕和显卡接口的具体细节。为了简单起点，我们可以用一段内存区域来表示屏幕，内存的一个 bit 就代表了屏幕中的一个像素。比如在屏幕中的 <code>(x,y)</code> 坐标绘制一个像素，可以用 <code>memory[x + y * rowSize] = 1</code> 来表示。从屏幕左上角开始，列是从左至右开始计数，行是从上至下开始计数。因此屏幕最左上角的坐标是 <code>(0,0)</code>。</p><p>为了简单起见，我们用 1 bit 来表示屏幕的一个像素，0 代表白色，1 代表黑色。屏幕每一行的长度用变量 <code>rowSzie</code> 表示，每一列的高度用 <code>colSize</code> 表示。</p><figure class="kg-card kg-image-card"><img src="https://pic4.zhimg.com/80/v2-6e4622b6e30abe0a476676e106b8d027_1440w.webp" class="kg-image" alt="v2-6e4622b6e30abe0a476676e106b8d027_1440w" width="496" height="358" loading="lazy"></figure><h3 id="--18">绘制线条</h3><p>如果我们要在计算机上绘制一条直线，那么只要知道计算机的起点坐标 <code>(x1,y1)</code> 和终点坐标 <code>(x2,y2)</code> 就可以了。</p><figure class="kg-card kg-image-card"><img src="https://pic2.zhimg.com/80/v2-4cb7322d209b50961a3979ee8e8e51bd_1440w.webp" class="kg-image" alt="v2-4cb7322d209b50961a3979ee8e8e51bd_1440w" width="400" height="246" loading="lazy"></figure><p>然后根据 <code>memory[x + y * rowSize] = 1</code> 公式，将 <code>(x1,y1)</code> 至 <code>(x2,y2)</code> 之间对应的内存区域置为 1，这样就画出来了一条直线。</p><h3 id="--19">绘制文本</h3><p>为了在屏幕上显示文本，首先必须将物理上基于像素点的屏幕，在逻辑上以字符为单位划分成若干区域，每个区域能输出单个完整的字符。假设有一个 256 行 512 列的屏幕，如果为每个字符分配一个 11*8 像素的网格，那么屏幕上总共能显示 23 行，每行 64 个字符（还有 3 行像素没使用）。</p><p>有了这些前提条件后，我们现在打算在屏幕上画一个 <code>A</code>：</p><figure class="kg-card kg-image-card"><img src="https://pic1.zhimg.com/80/v2-887b0d213e83b3958eb78c87f4b5d644_1440w.webp" class="kg-image" alt="v2-887b0d213e83b3958eb78c87f4b5d644_1440w" width="313" height="362" loading="lazy"></figure><p>上图的 <code>A</code> 在内存区域中用 11*8 像素的网格表示。为了在内存区域中绘制它，我们可以用一个二维数组来表示它：</p><pre><code class="language-js">const charA = [
 [0, 0, 1, 1, 0, 0, 0, 0], // 按从左至右的顺序来读取 bit，转换成十进制数字就是 12
 [0, 1, 1, 1, 1, 0, 0, 0], // 30
 [1, 1, 0, 0, 1, 1, 0, 0], // 51
 [1, 1, 0, 0, 1, 1, 0, 0], // 51
 [1, 1, 1, 1, 1, 1, 0, 0], // 63
 [1, 1, 0, 0, 1, 1, 0, 0], // 51
 [1, 1, 0, 0, 1, 1, 0, 0], // 51
 [1, 1, 0, 0, 1, 1, 0, 0], // 51
 [1, 1, 0, 0, 1, 1, 0, 0], // 51
 [0, 0, 0, 0, 0, 0, 0, 0], // 0
 [0, 0, 0, 0, 0, 0, 0, 0], // 0
]
</code></pre><p>上面二维数组的第一项，代表了第一行内存区域每个 bit 的取值。一共 11 行，画出了一个字母 <code>A</code>。</p><p>如果我们为 26 个字母都建一个映射表，按 ascii 的编码来排序，那么 <code>charsMap[65]</code> 就代表字符 <code>A</code>，当用户在键盘上按下 <code>A</code> 键时，就把 <code>charsMap[65]</code> 对应的数据输出到内存区域上，这样屏幕上就显示了一个字符 <code>A</code>。</p><h3 id="--20">绘制布局树</h3><p>科普完关于绘制屏幕的基础知识后，我们现在正式开始绘制布局树（为了方便，我们使用 <a href="https://link.zhihu.com/?target=https%3A//github.com/Automattic/node-canvas" rel="nofollow noreferrer">node-canvas</a> 库）。</p><p>首先要遍历整个布局树，然后逐个节点进行绘制：</p><pre><code class="language-ts">function renderLayoutBox(layoutBox: LayoutBox, ctx: CanvasRenderingContext2D, parent?: LayoutBox) {
    renderBackground(layoutBox, ctx)
    renderBorder(layoutBox, ctx)
    renderText(layoutBox, ctx, parent)
    for (const child of layoutBox.children) {
        renderLayoutBox(child, ctx, layoutBox)
    }
}
</code></pre><p>这个函数对每个节点依次绘制背景色、边框、文本，然后再递归绘制所有子节点。</p><p>默认情况下，HTML 元素按照它们出现的顺序进行绘制。如果两个元素重叠，则后一个元素将绘制在前一个元素之上。这种排序反映在我们的布局树中，它将按照元素在 DOM 树中出现的顺序绘制元素。</p><h3 id="--21">绘制背景色</h3><pre><code class="language-ts">function renderBackground(layoutBox: LayoutBox, ctx: CanvasRenderingContext2D) {
    const { width, height, x, y } = layoutBox.dimensions.borderBox()
    ctx.fillStyle = getStyleValue(layoutBox, 'background')
    ctx.fillRect(x, y, width, height)
}
</code></pre><p>首先拿到布局节点的位置、尺寸信息，以 <code>x,y</code> 作为起点，绘制矩形区域。并且以 CSS 属性 <code>background</code> 的值作为背景色进行填充。</p><h3 id="--22">绘制边框</h3><pre><code class="language-ts">function renderBorder(layoutBox: LayoutBox, ctx: CanvasRenderingContext2D) {
    const { width, height, x, y } = layoutBox.dimensions.borderBox()
    const { left, top, right, bottom } = layoutBox.dimensions.border
    const borderColor = getStyleValue(layoutBox, 'border-color')
    if (!borderColor) return

    ctx.fillStyle = borderColor

    // left
    ctx.fillRect(x, y, left, height)
    // top
    ctx.fillRect(x, y, width, top)
    // right
    ctx.fillRect(x + width - right, y, right, height)
    // bottom
    ctx.fillRect(x, y + height - bottom, width, bottom)
}
</code></pre><p>绘制边框，其实我们绘制的是四个矩形，每一个矩形就是一条边框。</p><h3 id="--23">绘制文本</h3><pre><code class="language-ts">function renderText(layoutBox: LayoutBox, ctx: CanvasRenderingContext2D, parent?: LayoutBox) {
    if (layoutBox.styleNode?.node.nodeType === NodeType.Text) {
        // get AnonymousBlock x y
        const { x = 0, y = 0, width } = parent?.dimensions.content || {}
        const styles = layoutBox.styleNode?.values || {}
        const fontSize = styles['font-size'] || '14px'
        const fontFamily = styles['font-family'] || 'serif'
        const fontWeight = styles['font-weight'] || 'normal'
        const fontStyle = styles['font-style'] || 'normal'

        ctx.fillStyle = styles.color
        ctx.font = `${fontStyle} ${fontWeight} ${fontSize} ${fontFamily}`
        ctx.fillText(layoutBox.styleNode?.node.nodeValue, x, y + parseInt(fontSize), width)
    }
}
</code></pre><p>通过 canvas 的 <code>fillText()</code> 方法，我们可以很方便的绘制带有字体风格、大小、颜色的文本。</p><h3 id="--24">输出图片</h3><p>绘制完成后，我们可以借助 <code>canvas</code> 的 API 输出图片。下面用一个简单的示例来演示一下：</p><pre><code class="language-html">&lt;html&gt;
    &lt;body id=" body " data-index="1" style="color: red; background: yellow;"&gt;
        &lt;div&gt;
            &lt;div class="lightblue test"&gt;test1!&lt;/div&gt;
            &lt;div class="lightblue test"&gt;
                &lt;div class="foo"&gt;foo&lt;/div&gt;
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/body&gt;
&lt;/html&gt;
* {
    display: block;
}

div {
    font-size: 14px;
    width: 400px;
    background: #fff;
    margin-bottom: 20px;
    display: block;
    background: lightblue;
}

.lightblue {
    font-size: 16px;
    display: block;
    width: 200px;
    height: 200px;
    background: blue;
    border-color: green;
    border: 10px;
}

.foo {
    width: 100px;
    height: 100px;
    background: red;
    color: yellow;
    margin-left: 50px;
}

body {
    display: block;
    font-size: 88px;
    color: #000;
}</code></pre><p>上面这段 HTML、CSS 代码经过渲染引擎程序解析后生成的图片如下：</p><figure class="kg-card kg-image-card"><img src="https://pic2.zhimg.com/80/v2-57e893eb457caeba4ceb5b70a77b8889_1440w.webp" class="kg-image" alt="v2-57e893eb457caeba4ceb5b70a77b8889_1440w" width="1000" height="500" loading="lazy"></figure><h3 id="--25">总结</h3><p>至此，这个玩具版的渲染引擎就完成了。虽然这个玩具并没有什么用，但如果能通过实现它来了解真实的渲染引擎是如何运作的，从这个角度来看，它还是“有用”的。</p><h3 id="--26">参考资料</h3><ul><li><a href="https://limpet.net/mbrubeck/2014/08/08/toy-layout-engine-1.html">Let's build a browser engine!</a></li><li><a href="https://github.com/mbrubeck/robinson">robinson</a></li><li><a href="https://developer.mozilla.org/zh-CN/docs/Web/Performance/How_browsers_work">渲染页面：浏览器的工作原理</a></li><li><a href="https://link.zhihu.com/?target=https%3A//developer.mozilla.org/zh-CN/docs/Web/Performance/Critical_rendering_path" rel="nofollow noreferrer">关键渲染路径</a></li><li><a href="https://link.zhihu.com/?target=https%3A//book.douban.com/subject/1998341/" rel="nofollow noreferrer">计算机系统要素</a></li></ul> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ 将图片变成 HTML 链接并在段落内嵌套链接 ]]>
                </title>
                <description>
                    <![CDATA[ 有的时候，你会想把链接嵌套在段落里，或者把图片变成链接。但你如何在 HTML 中这样做呢？ 在这篇文章中，我将通过代码实例向你展示如何在段落中嵌套链接，以及如何将图片变成链接。 如何在段落标签内嵌套锚标签 如果你想在你的段落中包含链接，那么你可以在段落标签中嵌套锚标签。 在这第一个例子中，我们有 “I love freeCodeCamp” 的文字。 <p>I love freeCodeCamp</p> 如果我想把 freeCodeCamp 这个词变成一个链接，那么我就把它包在一组锚标签里面。 <p>I love <a href="https://www.freecodecamp.org/">freeCodeCamp</a></p> 我们还可以添加 target="_blank" 属性，让该链接在新标签页中打开。 <p>I love <a target="_blank" href="https://www.freecodecamp.org/">freeCodeCamp</a></p> 当你把鼠标悬停在 freeCodeCamp 这个词上时，你会发现它是一个链接，你现在可 ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/how-to-turn-text-and-images-into-links-using-html/</link>
                <guid isPermaLink="false">6460ef710f634b0716652ec7</guid>
                
                    <category>
                        <![CDATA[ HTML ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Chengjun.L ]]>
                </dc:creator>
                <pubDate>Thu, 11 May 2023 03:22:00 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2023/05/markus-spiske--dbOrdtrR1A-unsplash.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>原文：</strong> <a href="https://www.freecodecamp.org/news/how-to-turn-text-and-images-into-links-using-html/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">HTML Link – How to Turn an Image into a Link and Nest Links Inside Paragraphs</a>
      </p><p>有的时候，你会想把链接嵌套在段落里，或者把图片变成链接。但你如何在 HTML 中这样做呢？</p><p>在这篇文章中，我将通过代码实例向你展示如何在段落中嵌套链接，以及如何将图片变成链接。</p><h2 id="-">如何在段落标签内嵌套锚标签</h2><p>如果你想在你的段落中包含链接，那么你可以在段落标签中嵌套锚标签。</p><p>在这第一个例子中，我们有 “I love freeCodeCamp” 的文字。</p><pre><code class="language-html">&lt;p&gt;I love freeCodeCamp&lt;/p&gt;</code></pre><p>如果我想把 freeCodeCamp 这个词变成一个链接，那么我就把它包在一组锚标签里面。</p><pre><code class="language-html">&lt;p&gt;I love &lt;a href="https://www.freecodecamp.org/"&gt;freeCodeCamp&lt;/a&gt;&lt;/p&gt;</code></pre><p>我们还可以添加 <code>target="_blank"</code> 属性，让该链接在新标签页中打开。</p><pre><code class="language-html">&lt;p&gt;I love &lt;a target="_blank" href="https://www.freecodecamp.org/"&gt;freeCodeCamp&lt;/a&gt;&lt;/p&gt;</code></pre><p>当你把鼠标悬停在 freeCodeCamp 这个词上时，你会发现它是一个链接，你现在可以点击它，它将引导你进入网站。</p><figure class="kg-card kg-embed-card"><iframe id="cp_embed_BaYVREm" src="https://codepen.io/jessica-wilkins/embed/preview/BaYVREm?default-tabs=html%2Cresult&amp;height=300&amp;host=https%3A%2F%2Fcodepen.io&amp;slug-hash=BaYVREm" title="Embedded content" scrolling="no" frameborder="0" height="300" allowtransparency="true" class="cp_embed_iframe" loading="lazy" style="box-sizing: inherit; margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 22px; vertical-align: middle; width: 720px; overflow: hidden;"></iframe></figure><p>当你想把你的用户引导到与页面上的主要内容有关的额外信息时，可以在段落标签内嵌套链接。</p><p>在下一个例子中，我有一个关于 freeCodeCamp 的课程的段落。</p><pre><code class="language-html">&lt;p&gt;I started learning how to code using freeCodeCamp. I really enjoyed their Responsive Web Design course. I am looking forward to starting the JavaScript course soon.&lt;/p&gt;</code></pre><p>我想首先把 freeCodeCamp 这个词变成一个链接，把人们引向网站。</p><pre><code class="language-html">&lt;p&gt;I started learning how to code using  &lt;a href="https://www.freecodecamp.org/"&gt;freeCodeCamp&lt;/a&gt;. I really enjoyed  their Responsive Web Design course. I am looking forward to starting the  JavaScript course soon.&lt;/p&gt;</code></pre><p>现在我将添加另一个 “Responsive Web Design course” 的链接，这将引导人们进入基于项目的课程。</p><pre><code class="language-html">&lt;p&gt;I started learning how to code using  &lt;a href="https://www.freecodecamp.org/"&gt;freeCodeCamp&lt;/a&gt;. I really enjoyed  their  &lt;a href="https://www.freecodecamp.org/learn/2022/responsive-web-design/"&gt;Responsive Web Design course&lt;/a&gt;. I am looking forward to starting the JavaScript course soon.&lt;/p&gt;</code></pre><p>最后，我将为 JavaScript 课程添加一个链接，这将引导用户进入 JavaScript 课程。</p><pre><code class="language-html">&lt;p&gt;I started learning how to code using &lt;a href="https://www.freecodecamp.org/"&gt;freeCodeCamp&lt;/a&gt;. I really enjoyed their &lt;a href="https://www.freecodecamp.org/learn/2022/responsive-web-design/"&gt;Responsive Web Design course&lt;/a&gt;. I am looking forward to starting the &lt;a href="https://www.freecodecamp.org/learn/javascript-algorithms-and-data-structures/"&gt;JavaScript course&lt;/a&gt; soon.&lt;/p&gt;</code></pre><p>这就是 web 浏览器中展示的样子：</p><figure class="kg-card kg-embed-card"><iframe id="cp_embed_ExQRmqY" src="https://codepen.io/jessica-wilkins/embed/preview/ExQRmqY?default-tabs=html%2Cresult&amp;height=300&amp;host=https%3A%2F%2Fcodepen.io&amp;slug-hash=ExQRmqY" title="Embedded content" scrolling="no" frameborder="0" height="300" allowtransparency="true" class="cp_embed_iframe" loading="lazy" style="box-sizing: inherit; margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 22px; vertical-align: middle; width: 720px; overflow: hidden;"></iframe></figure><h2 id="--1">如何将图片变成链接</h2><p>在 HTML 中，我们可以使用 <code>&lt;img&gt;</code> 元素来在页面上添加图片。在这个例子中，我们要添加一张五只猫的图片。</p><pre><code class="language-html">&lt;img  src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/cats.jpg"  alt="Five cats looking around a field."/&gt;</code></pre><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2022/06/Screen-Shot-2022-06-02-at-10.39.02-PM.png" class="kg-image" alt="Screen-Shot-2022-06-02-at-10.39.02-PM" width="600" height="400" loading="lazy"></figure><p><br>如果我们想让该图片成为一个可点击的链接，那么我们可以把它放在一组锚标签里面。</p><pre><code class="language-html">&lt;a href="https://en.wikipedia.org/wiki/Cat"&gt;&lt;img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/cats.jpg" alt="Five cats looking around a field."/&gt;&lt;/a&gt;</code></pre><p>我们还可以添加 <code>target="_blank"</code> 属性，让该链接在新标签页中打开。</p><pre><code class="language-html">&lt;a target="_blank" href="https://en.wikipedia.org/wiki/Cat"&gt;&lt;img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/cats.jpg" alt="Five cats looking around a field." /&gt;&lt;/a&gt;</code></pre><p>当你把鼠标悬停在图片上时，你会看到光标指针，表明它是一个链接，引导你进入一篇关于猫的文章。</p><figure class="kg-card kg-embed-card"><iframe id="cp_embed_XWZYRgy" src="https://codepen.io/jessica-wilkins/embed/preview/XWZYRgy?default-tabs=html%2Cresult&amp;height=300&amp;host=https%3A%2F%2Fcodepen.io&amp;slug-hash=XWZYRgy" title="Embedded content" scrolling="no" frameborder="0" height="300" allowtransparency="true" class="cp_embed_iframe" loading="lazy" style="box-sizing: inherit; margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 22px; vertical-align: middle; width: 720px; overflow: hidden;"></iframe></figure><h2 id="--2">总结</h2><p>在这篇文章中，我们学习了如何在段落中嵌套锚标签，以及如何将图片变成链接。</p><p>为了在段落中添加链接，我们可以在段落标签中嵌套锚标签。</p><pre><code class="language-html">&lt;p&gt;I love &lt;a href="https://www.freecodecamp.org/"&gt;freeCodeCamp&lt;/a&gt;&lt;/p&gt;</code></pre><p>为了把图片变成一个链接，我们可以把一个 <code>img</code> 元素嵌套在锚标签里面。</p><pre><code class="language-html">&lt;a href="https://en.wikipedia.org/wiki/Cat"&gt;&lt;img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/cats.jpg" alt="Five cats looking around a field."/&gt;&lt;/a&gt;</code></pre><p>我希望你喜欢这篇文章，祝你在编程之旅中好运。</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ 如何使用 CSS Font Weight 属性在 HTML 中加粗文本 ]]>
                </title>
                <description>
                    <![CDATA[ CSS 是 web 开发者的一个强大工具。它允许你以各种方式设置 HTML 内容的样式。 一种常见的格式化技术是使用 font-weight 属性将文本加粗。粗体字可以增加对关键信息的强调，创造视觉对比，并提高内容的可读性。 在这篇文章中，你将学习如何使用 CSS font-weight 属性在 HTML 中将文本加粗。无论你是初学者还是有经验的开发者，本文都将为你提供一个全面的指南，让你在 HTML 内容中使用 CSS 创建粗体文本。 理解 Font-Weight 属性 font-weight 属性是一个 CSS 属性，它决定了文本的粗细程度，数值越高表示字体越粗。 font-weight 属性接受各种数值，包括数字和关键字值。 数值范围从 100 到900，增量为 100。正常粗细的值是 400，而 700 的值被认为是粗体。一些常用的关键字值包括 bold、bolder、 lighter 和 normal。 如何用 CSS 创建粗体字 在 HTML 中使用 CSS 创建粗体字是一个简单的过程，可以通过几种方式实现。你可以选择使用任何形式的样式，如内联、内部或外部样式。 ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/css-bold-how-to-bold-text-in-html-with-font-weight/</link>
                <guid isPermaLink="false">64216c6ce32a7606487d5982</guid>
                
                    <category>
                        <![CDATA[ CSS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ HTML ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Miya Liu ]]>
                </dc:creator>
                <pubDate>Mon, 27 Mar 2023 04:29:00 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2023/03/kobu-agency-ipARHaxETRk-unsplash.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>原文：</strong> <a href="https://www.freecodecamp.org/news/css-bold-how-to-bold-text-in-html-with-font-weight/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">CSS Bold – How to Bold Text in HTML with Font Weight</a>
      </p><p>CSS 是 web 开发者的一个强大工具。它允许你以各种方式设置 HTML 内容的样式。</p><p>一种常见的格式化技术是使用 <code>font-weight</code> 属性将文本加粗。粗体字可以增加对关键信息的强调，创造视觉对比，并提高内容的可读性。</p><p>在这篇文章中，你将学习如何使用 CSS <code>font-weight</code> 属性在 HTML 中将文本加粗。无论你是初学者还是有经验的开发者，本文都将为你提供一个全面的指南，让你在 HTML 内容中使用 CSS 创建粗体文本。</p><h2 id="-font-weight-">理解 Font-Weight 属性</h2><p><code>font-weight</code> 属性是一个 CSS 属性，它决定了文本的粗细程度，数值越高表示字体越粗。</p><p><code>font-weight</code> 属性接受各种数值，包括数字和关键字值。</p><p>数值范围从 100 到900，增量为 100。正常粗细的值是 400，而 700 的值被认为是粗体。一些常用的关键字值包括 <code>bold</code>、<code>bolder</code>、<code>lighter</code> 和 <code>normal</code>。</p><h2 id="-css-">如何用 CSS 创建粗体字</h2><p>在 HTML 中使用 CSS 创建粗体字是一个简单的过程，可以通过几种方式实现。你可以选择使用任何形式的样式，如内联、内部或外部样式。</p><h3 id="-">如何用内联样式创建粗体字</h3><p>你可以使用内联样式，将 <code>font-weight</code> 属性直接应用于特定的 HTML 元素，就像这样：</p><pre><code class="language-html">&lt;p style="font-weight: bold;"&gt;This is a bold text&lt;/p&gt;
</code></pre><p>然而，内联样式会使你的 HTML 代码变得杂乱无章，难以维护，特别是当许多元素需要相同的样式时。</p><h3 id="--1">如何用内部样式创建粗体字</h3><p>内部样式设计允许你在 HTML 文档的 <code>head</code> 部分使用 <code>style</code> 标签来应用 CSS 样式，像这样：</p><pre><code class="language-html">&lt;head&gt;
  &lt;style&gt;
    p {
      font-weight: bold;
    }
  &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;p&gt;This is a bold text&lt;/p&gt;
&lt;/body&gt;
</code></pre><p>这种方法在对一个页面上的多个元素应用相同的样式时很有用。</p><h3 id="--2">如何用外部样式创建粗体字</h3><p>外部样式设计包括创建一个单独的 CSS 文件，并使用 <code>link</code> 标签将其链接到你的 HTML 文档中，像这样：</p><pre><code class="language-html">&lt;head&gt;
  &lt;link rel="stylesheet" type="text/css" href="styles.css"&gt;
&lt;/head&gt;
</code></pre><p>CSS 文件可以包含你网站上所有 HTML 元素的样式，你可以很容易地对这些样式进行修改，而不必修改 HTML 代码。</p><pre><code class="language-css">p {
  font-weight: bold;
}
</code></pre><h2 id="-html-">在 HTML 中使用粗体字的最佳实践</h2><p>虽然在 HTML 中使用粗体字可以帮助强调重要的信息，但必须遵循最佳实践，以确保文本的可读性和可访问性。</p><p>以下是在 HTML 中使用粗体字的一些最佳实践：</p><p><strong>选择正确的 font-weight：</strong>在使用粗体字时，必须选择正确的 font-weight，以确保文本清晰易读。</p><p>较粗的 font-weight 可能适合于标题，较细的字体可能更适合于正文。同样重要的是，要确保粗体字不会太过压抑，也不会影响到页面上的其他元素。</p><p><strong>平衡粗体字和其他格式化选项的关系：</strong>虽然粗体字可以成为吸引人们注意重要信息的有力方式，但重要的是要将它与其他格式选项相平衡，以创造视觉层次。</p><p>你可以使用其他样式，如斜体、下划线或不同的字体大小或颜色，来区分不同的重要程度。</p><p><strong>避免过度使用粗体字：</strong>过度使用粗体字会使文字更难阅读，并有损页面的整体设计。</p><p>重要的是要少用粗体字，只在有必要强调重要信息的地方使用。避免在整个段落或文本块中使用粗体字，因为这可能使读者难以区分重要信息和普通文本。</p><p><strong>测试无障碍性：</strong>当使用粗体字时，必须确保所有用户，包括有视力障碍的用户，都能使用。</p><p>屏幕阅读器可能难以阅读粗体文本，因此，使用无障碍工具测试页面，以确保粗体字格式正确，兼顾无障碍，是很重要的。</p><h2 id="--3"><strong>总结</strong></h2><p>总之，在 HTML 中使用粗体字可以有效地强调重要信息，并创造视觉层次。</p><p>通过选择合适的 font-weight，平衡粗体字与其他格式选项，避免过度使用，并进行无障碍测试，你可以确保粗体字保持可读性，并让所有用户都能使用。</p><p>谢谢你阅读本文，happy coding！</p><p>你可以<a href="https://joelolawanle.com/contents">访问我的网站</a>，阅读我的 188 篇文章。你也可以使用搜索栏来查看我是否写过特定的文章。</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ 用 HTML5 写一个基本的 index.html 模板文件 ]]>
                </title>
                <description>
                    <![CDATA[ HTML 有不同的标签，其中一些标签有语义的含义。一个 HTML 文件的基本模板看起来像这样： <!DOCTYPE html> <html lang="en">   <head>     <meta charset="UTF-8">     <meta name="viewport" content="width=device-width, initial-scale=1.0">     <meta http-equiv="X-UA-Compatible" content="ie=edge">     <title>My Website</title>     <link rel="stylesheet" href="./style.css">     <link ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/html-starter-template-a-basic-html5-boilerplate-for-index-html/</link>
                <guid isPermaLink="false">64211a9de32a7606487d5837</guid>
                
                    <category>
                        <![CDATA[ HTML ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Miya Liu ]]>
                </dc:creator>
                <pubDate>Tue, 21 Mar 2023 04:49:00 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2023/03/pexels-pixabay-270404.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>原文：</strong> <a href="https://www.freecodecamp.org/news/html-starter-template-a-basic-html5-boilerplate-for-index-html/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">HTML Starter Template – A Basic HTML5 Boilerplate for index.html</a>
      </p><p>HTML 有不同的标签，其中一些标签有语义的含义。一个 HTML 文件的基本模板看起来像这样：</p><pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
  &lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
    &lt;meta http-equiv="X-UA-Compatible" content="ie=edge"&gt;
    &lt;title&gt;My Website&lt;/title&gt;
    &lt;link rel="stylesheet" href="./style.css"&gt;
    &lt;link rel="icon" href="./favicon.ico" type="image/x-icon"&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;main&gt;
        &lt;h1&gt;Welcome to My Website&lt;/h1&gt;  
    &lt;/main&gt;
	&lt;script src="index.js"&gt;&lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;
</code></pre><p>在本文的其余部分，我将解释这个模板的每一部分是什么意思。</p><h1 id="html-"><strong>HTML 模板语法</strong></h1><h2 id="doctype"><strong>DOCTYPE</strong></h2><pre><code class="language-html">&lt;!DOCTYPE html&gt;
</code></pre><p>这个元素是 HTML 文件的 doctype 声明。<code>&lt;!DOCTYPE html&gt;</code> 告诉浏览器将 HTML 代码渲染成 HTML5（而不是其他版本的 HTML）。</p><p>这一点很重要，因为如果没有这个声明，像 <code>section</code>、<code>article</code> 等 HTML5 元素可能不会被正确呈现。</p><h2 id="html--1"><strong>html 标签</strong></h2><pre><code class="language-html">&lt;html lang="en"&gt;
    ...
&lt;/html&gt;
</code></pre><p><code>html</code> 标签是 HTML 文档的根。它包含了 <code>head</code> 标签、<code>body</code> 标签以及网站中使用的其他所有 HTML 元素（除了 DOCTYPE）。</p><p>它也有 <code>lang</code> 属性，你可以用它来指定网站上文本内容的语言。默认值是 “unknown”，所以建议你总是指定一种语言。</p><p>定义语言有助于屏幕阅读器正确阅读单词，也有助于搜索引擎返回特定语言的搜索结果。</p><h2 id="head-"><strong>head 标签</strong></h2><pre><code class="language-html">&lt;head&gt;
    ...
&lt;/head&gt;
</code></pre><p><code>head</code> 标签容纳了你的网站的元数据。这些是用户在视觉上看不到的数据，但它们提供了关于你网站内容的信息。搜索引擎特别使用这些数据对你的网站进行排名。</p><p><code>head</code> 标签中的 <code>metadata</code> 包括 <code>meta</code> 标签、<code>title</code> 标签、<code>link</code> 标签、脚本、样式表，以及更多。</p><h2 id="meta-"><strong>meta 标签</strong></h2><pre><code class="language-html">&lt;meta ... /&gt;
</code></pre><p><code>meta</code> 标签是一个元数据元素，用于为你的网站添加更多的元数据，而不是像 <code>title</code> 这样的非元标签所提供的那种。</p><p>你可以将这些标签用于各种目的：</p><ul><li>为社交媒体平台添加元数据，以创建链接预览</li><li>为你的网站添加一个描述</li><li>为你的网站添加一个字符编码</li><li>以及更多。</li></ul><p>搜索引擎、社交媒体平台和 web 服务使用这些元数据来了解你的网站内容，并决定如何向用户展示它们。</p><h2 id="title-"><strong>title 标签</strong></h2><pre><code class="language-html">&lt;title&gt;My Website&lt;/title&gt;
</code></pre><p><code>title</code> 标签是用来为你的网站指定一个标题。你的浏览器使用它来在标题栏中显示一个标题：</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/news/content/images/2022/03/Screenshot-2022-03-25-at-07.38.56.png" class="kg-image" alt="Screenshot-2022-03-25-at-07.38.56" width="600" height="400" loading="lazy"></figure><p>这个标签也有助于搜索引擎在其搜索结果中显示你的网站的标题：</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/news/content/images/2022/03/Screenshot-2022-03-25-at-07.44.11.png" class="kg-image" alt="Screenshot-2022-03-25-at-07.44.11" width="600" height="400" loading="lazy"></figure><h2 id="link-"><strong>link 标签</strong></h2><p>你使用 <code>link</code> 标签，顾名思义，是为了链接到另一个文档。通常情况下，这在当前文档和一个单独的文档之间建立了不同种类的关系。</p><pre><code class="language-html">&lt;link rel="stylesheet" href="./style.css"&gt;
</code></pre><p>例如，从上面的代码块中可以看出，我们已经与 <code>style.css</code> 文件建立了一个 “stylesheet” 文档关系。</p><p>这个标签最常见的用途是将样式表添加到文档中，同时也将 favicons 添加到网站中：</p><pre><code class="language-html">&lt;link rel="icon" href="./favicon.ico" type="image/x-icon"&gt;
</code></pre><p>图标是靠近网页标题的一个小图片，如下图所示：</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/news/content/images/2022/03/Screenshot-2022-03-25-at-07.38.56-1.png" class="kg-image" alt="Screenshot-2022-03-25-at-07.38.56-1" width="600" height="400" loading="lazy"></figure><h2 id="body-"><strong>body 标签</strong></h2><pre><code class="language-html">&lt;body&gt;
    ...
&lt;/body&gt;
</code></pre><p><code>body</code> 标签容纳了网站的主体内容，对用户来说是可见的。虽然像 <code>style</code> 和 <code>script</code> 这样的非可见元素也可以添加到这里，但 <code>body</code> 标签里的大多数标签通常是可见的。</p><p>从标题到段落到媒体等等，这些元素都被添加在这里。任何没有在这里找到的元素（可以包含在 <code>head</code> 标签中）都不会在屏幕上显示。</p><h2 id="main-"><strong>main 标签</strong></h2><pre><code class="language-html">&lt;main&gt;
    ...
&lt;/main&gt;
</code></pre><p><code>main</code> 标签规定了一个网站的基本内容。这将是与网站标题相关的内容。</p><p>例如，一个博客文章页面。左边的社交媒体分享、右边的广告、页眉和页脚是网页的次要部分。显示封面图片、标题和帖子文本内容的帖子本身是中心部分，将在 <code>main</code> 元素中。</p><h2 id="h1-"><strong>h1 标签</strong></h2><p>HTML 有不同的标题元素，包括 <code>h1</code>、<code>h2</code>、<code>h3</code>、<code>h4</code>、<code>h5</code> 和 <code>h6</code>。标题元素被用来描述网页的不同部分。而这些元素有一个顺序，<code>h1</code> 是最高的。</p><p>你在一个网页上只应该有一个 <code>h1</code> 元素，因为它是主要部分开始的地方。然后，你还有其他章节和子章节，你可以使用其他标题元素。</p><p>另外，请注意，你不应该跳过标题。例如，你不应该在使用 <code>h2</code> 元素之后使用 <code>h4</code> 元素。一个好的结构可以是这样的：</p><pre><code class="language-html">&lt;h1&gt;Welcome to my website&lt;/h1&gt;

&lt;h2&gt;What do I have to offer&lt;/h2&gt;

&lt;h3&gt;1. Financial Benefits&lt;/h3&gt;

&lt;h3&gt;2. Society improves&lt;/h3&gt;

&lt;h4&gt;a. Improving the tax system&lt;/h4&gt;

&lt;h4&gt;b. Providing more refuse dumps&lt;/h4&gt;

&lt;h2&gt;Who am I&lt;/h2&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;
</code></pre><p>从这段代码中，你可以看到标题层如何指定它们在章节和子章节中的位置。</p><h1 id="-">总结</h1><p>在这篇文章中，我们已经看到了一个 HTML 启动模板，以及这个模板中使用的每个标签的含义。</p><p>这个元素列表并非详尽无遗，在 head 标签和 body 标签中还可以找到更多的元素，而且还有许多属性。</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ 在新标签页中打开一个链接——详解 HTML target blank 属性 ]]>
                </title>
                <description>
                    <![CDATA[ 有些时候，你会希望你的用户点击一个网站链接，并在一个新的浏览器标签页中打开它。但你如何在 HTML 中做到这一点呢？ 在这篇文章中，我将通过代码实例告诉你如何使用 target="_blank" 属性。我还将谈到什么时候你应该考虑使用这个属性。 如何使用 target="_blank" 打开一个新的标签页 应该在锚标签开始标签内使用 target="_blank" 属性，像这样： <a href="website-link-goes-here" target="_blank"> 当用户点击该链接时，将自动在一个新的浏览器标签页打开该页面。 在这个例子中，我在一组段落标签中嵌套了一个链接，以引导人们到 freeCodeCamp。 <p>To learn how to code for free, please visit <a href="https://www.freecodecamp.org/learn" target="_blank">freeCodeCamp.org</a></p> 当你点击 freeCodeCamp 的链接时，它将为你打开一个新的浏览器标签页。  ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/how-to-open-a-link-in-a-new-tab/</link>
                <guid isPermaLink="false">64143c325e1a4c068f38cf88</guid>
                
                    <category>
                        <![CDATA[ HTML ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Miya Liu ]]>
                </dc:creator>
                <pubDate>Mon, 13 Mar 2023 06:19:00 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2023/03/markus-spiske-4qbS830djfs-unsplash.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>原文：</strong> <a href="https://www.freecodecamp.org/news/how-to-open-a-link-in-a-new-tab/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">How to Open a Link in a New Tab – HTML target blank Attribute Explained</a>
      </p><p>有些时候，你会希望你的用户点击一个网站链接，并在一个新的浏览器标签页中打开它。但你如何在 HTML 中做到这一点呢？</p><p>在这篇文章中，我将通过代码实例告诉你如何使用 <code>target="_blank"</code> 属性。我还将谈到什么时候你应该考虑使用这个属性。</p><h2 id="-target-_blank-"><strong>如何使用 </strong><code><strong>target="_blank"</strong></code><strong> 打开一个新的标签页</strong></h2><p>应该在锚标签开始标签内使用 <code>target="_blank"</code> 属性，像这样：</p><pre><code class="language-html">&lt;a href="website-link-goes-here" target="_blank"&gt;</code></pre><p>当用户点击该链接时，将自动在一个新的浏览器标签页打开该页面。</p><p>在这个例子中，我在一组段落标签中嵌套了一个链接，以引导人们到 freeCodeCamp。</p><pre><code class="language-html">&lt;p&gt;To learn how to code for free, please visit &lt;a href="https://www.freecodecamp.org/learn" target="_blank"&gt;freeCodeCamp.org&lt;/a&gt;&lt;/p&gt;</code></pre><p>当你点击 freeCodeCamp 的链接时，它将为你打开一个新的浏览器标签页。</p><figure class="kg-card kg-embed-card"><iframe id="cp_embed_zYRRdmQ" src="https://codepen.io/jessica-wilkins/embed/preview/zYRRdmQ?default-tabs=html%2Cresult&amp;height=300&amp;host=https%3A%2F%2Fcodepen.io&amp;slug-hash=zYRRdmQ" title="Embedded content" scrolling="no" frameborder="0" height="300" allowtransparency="true" class="cp_embed_iframe" loading="lazy" style="box-sizing: inherit; margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 22px; vertical-align: middle; width: 720px; overflow: hidden;"></iframe></figure><p>如果我省略 <code>target="_blank"</code> &nbsp;属性，那么默认行为就是离开当前网页，直接进入该链接，而不打开新的浏览器标签页。</p><h2 id="noopener-"><code><strong>noopener</strong></code><strong> 关键词是什么</strong></h2><p><code>rel</code> 属性中的 <code>noopener</code> 关键词主要是出于安全考虑，以防止恶意用户通过 <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/opener">Window.opener</a></code> 属性对原始网页进行破坏。如果恶意用户获得了对你的窗口对象的访问权，那么他们可以将你的页面重定向到一个恶意的 URL。</p><p>你可以使用 <code>noopener</code> 关键词来防止这种安全问题发生。下面是 <code>noopener</code> 关键词的使用方法：</p><pre><code class="language-html">&lt;a target="_blank" rel="noopener" href="https://devdocs.io/html/element/heading_elements"&gt;DevDocs documentation&lt;/a&gt;</code></pre><p>如果你想了解更多关于 <code>rel=noopener</code> 帮助解决安全问题的信息，请阅读这篇有帮助的<a href="https://mathiasbynens.github.io/rel-noopener/">文章</a>。</p><h3 id="-noopener-"><strong>对 <code>noopener</code> 关键词的更新</strong></h3><p>在 2021 年，有一个更新，现代浏览器现在对任何使用 <code>target=_blank</code> 属性的链接设置 <code>rel=noopener</code>。正如你在这个“<a href="https://caniuse.com/rel-noopener">我可以使用吗</a>”表中所看到的，除了 Internet Explorer 11，大多数浏览器都支持 <code>noopener</code> 关键词。</p><p>即使有了这个更新，很多开发者仍然会对使用 <code>target=_blank</code> 属性的链接使用 <code>rel=noopener</code>。</p><h2 id="-target-_blank--1"><strong>你应该一直使用 <code>target="_blank"</code> 属性吗</strong></h2><p>当用户点击一个链接时，默认行为是让该链接在用户所在的当前页面上打开，而不打开一个新的浏览器标签页。在很多情况下，你并不想改变这种默认行为，因为用户已经习惯了这种行为。</p><p>你必须仔细考虑何时是使用 <code>target="_blank"</code> 属性的好时机。一个很好的例子是，如果用户正在一个页面上工作，如果她们点击了一个链接，她们不想离开这个页面。</p><p>在这个例子中，我们正在链接到 <a href="https://devdocs.io/">DevDocs</a> 文档，所以用户可以留在他们当前的页面上，在新的标签页上查找参考资料。</p><figure class="kg-card kg-embed-card"><iframe id="cp_embed_qBxxPdb" src="https://codepen.io/jessica-wilkins/embed/preview/qBxxPdb?default-tabs=html%2Cresult&amp;height=300&amp;host=https%3A%2F%2Fcodepen.io&amp;slug-hash=qBxxPdb" title="Embedded content" scrolling="no" frameborder="0" height="300" allowtransparency="true" class="cp_embed_iframe" loading="lazy" style="box-sizing: inherit; margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 22px; vertical-align: middle; width: 720px; overflow: hidden;"></iframe></figure><h2 id="-"><strong>总结</strong></h2><p>如果你希望你的用户点击一个链接，打开一个新的浏览器标签页，你可以使用 <code>target="_blank"</code> 属性。</p><p><code>target="_blank"</code> 属性是在锚标签开始标签内使用的，像这样：</p><pre><code class="language-html">&lt;a href="website-link-goes-here" target="_blank"&gt;</code></pre><p>在 <code>rel</code> 属性中添加 <code>noopener</code> 关键词是为了防止恶意用户通过 <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/opener">Window.opener</a></code><a href="https://chinese.freecodecamp.org/news/how-to-open-a-link-in-a-new-tab/%E6%B7%BB%E5%8A%A0rel%E5%B1%9E%E6%80%A7%E4%B8%AD%E7%9A%84noopener%E5%85%B3%E9%94%AE%E5%AD%97%E6%98%AF%E4%B8%BA%E4%BA%86%E9%98%B2%E6%AD%A2%E6%81%B6%E6%84%8F%E7%94%A8%E6%88%B7%E9%80%9A%E8%BF%87Window.opener%E5%B1%9E%E6%80%A7%E6%9D%A5%E6%89%B0%E4%B9%B1%E5%8E%9F%E5%A7%8B%E7%BD%91%E9%A1%B5%E3%80%82"> 属性来扰乱原始网页。</a></p><pre><code class="language-html">&lt;a target="_blank" rel="noopener" href="link-goes-here"&gt;</code></pre><p>你必须仔细考虑何时是使用 <code>target="_blank"</code> 属性的好时机，因为你不希望总是改变链接的默认行为。</p><p>我希望你喜欢这篇文章，祝你在编程之旅中好运。</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ HTML 中的文本框——输入字段 HTML 标签 ]]>
                </title>
                <description>
                    <![CDATA[ 在这篇文章中，你将学习如何在 HTML 中创建一个文本输入字段。你还将了解 web 表单，并对其工作原理有一个概括的认识，因为文本框是表单的共同特征。 让我们开始吧！ web 表单是什么 表单是收集信息的一种有效方式。 在很多情况下，你需要填写一个实体的表格、一个打印的实体文件，并提供个人的详细资料。 例如，当你开始一份新工作时，或当你去做体检时，或当你在租/买房子的过程中，或任何其他需要文书工作的时候，你可能会填写一份表格并把它交给某人。 就像实体表格一样，在线数字 web 表单是一种使用 web 技术组合的方式来接收和收集用户和访问者的输入、信息和重要数据。 web 表格模仿物理表格，包含供用户填写信息的空格。 web 表单使用各种工具或表格控件来收集用户的输入。 一个网站可以有一个搜索框，或一个文本输入栏，用于输入一行文本。这使用户能够搜索特定的东西。 一个网站也可以包含一个注册表，让用户注册一个新闻简报或其他更新。 这通常会包含一个文本输入字段，用于输入用户的名字、姓氏和电子邮件地址。 当用户在进行网上购物时，许多网站也有注册/登录表单。例如，用户在一个文 ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/text-box-in-html-the-input-field-html-tag/</link>
                <guid isPermaLink="false">63e89386e673d23d288787bf</guid>
                
                    <category>
                        <![CDATA[ HTML ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Miya Liu ]]>
                </dc:creator>
                <pubDate>Wed, 08 Feb 2023 08:18:00 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2023/02/aaron-burden-y02jEX_B0O0-unsplash.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>原文：</strong> <a href="https://www.freecodecamp.org/news/text-box-in-html-the-input-field-html-tag/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">Text Box in HTML – The Input Field HTML Tag</a>
      </p><p>在这篇文章中，你将学习如何在 HTML 中创建一个文本输入字段。你还将了解 web 表单，并对其工作原理有一个概括的认识，因为文本框是表单的共同特征。</p><p>让我们开始吧！</p><h2 id="web-">web 表单是什么</h2><p>表单是收集信息的一种有效方式。</p><p>在很多情况下，你需要填写一个实体的表格、一个打印的实体文件，并提供个人的详细资料。</p><p>例如，当你开始一份新工作时，或当你去做体检时，或当你在租/买房子的过程中，或任何其他需要文书工作的时候，你可能会填写一份表格并把它交给某人。</p><p>就像实体表格一样，在线数字 web 表单是一种使用 web 技术组合的方式来接收和收集用户和访问者的输入、信息和重要数据。</p><p>web 表格模仿物理表格，包含供用户填写信息的空格。</p><p>web 表单使用各种工具或表格控件来收集用户的输入。</p><p>一个网站可以有一个搜索框，或一个文本输入栏，用于输入一行文本。这使用户能够搜索特定的东西。</p><p>一个网站也可以包含一个注册表，让用户注册一个新闻简报或其他更新。</p><p>这通常会包含一个文本输入字段，用于输入用户的名字、姓氏和电子邮件地址。</p><p>当用户在进行网上购物时，许多网站也有注册/登录表单。例如，用户在一个文本字段中输入他们的用户名，在另一个字段中输入他们的密码。虽然密码字段也是文本字段，但每个文本字符都被一个黑点所掩盖，以隐藏正在输入的内容。</p><p>一个网站也可以有一个较大的文本区域，供用户输入较长的文本段落，这对于在博客文章下面留下评论是很有用的。</p><p>许多表单还允许用户通过选择一个单选按钮从若干选项中选择一个特定的选项。它们可以让用户通过选中/不选中复选框来选择一个以上的选项。</p><p>最后，所有的表单都有一个提交按钮，将数据提交给服务器，在服务器存储或处理数据。</p><h2 id="web--1">web 表单如何运行</h2><p>互联网是一个大型的全球网络，连接着世界各地数以百万计的计算机。</p><p>作为网络一部分的计算机通过发送和接收信息相互通信。</p><p>实现这一目的的方式是得益于 web 客户端/服务器请求/响应架构。</p><p>客户端，通常是一个 web 浏览器，如谷歌浏览器，向 web 服务器发送一个请求。</p><p>web 服务器是一块计算机硬件或软件，用于存储构成网站的文件，并在收到请求时分发这些文件。</p><p>该请求可能是要查看作为网页一部分的表单。</p><p>服务器将构成 web 表单的文件作为响应发送回来。然后，web 浏览器将这些文件组合在一起，用户在 web 浏览器中查看表单。</p><p>这个请求/响应循环是由一个协议构成的，叫作 HTTP（代表 HyperText Transfer Protocol 超文本传输协议）。</p><p>因此，当使用一个 web 表单时，用户输入必要的数据，然后经过客户端验证，检查是否填写了所有需要的字段，以及数据的格式是否正确，用户点击提交按钮。</p><p>然后，数据在 HTTP 请求中以<em>名-值</em>对的形式被发送到服务器上。这种用<em>名-值</em>对组织信息的方法可以确保正确的数据与正确的表单元素相对应。</p><p>然后，一个服务器端语言，如 PHP、Ruby 或 Python，被用来处理信息，并将其存储在数据库中，以便以后使用或检索。</p><h2 id="-html-web-">如何在 HTML 中创建 web 表单</h2><p>要在 HTML 中创建一个表单，你需要使用 <code>&lt;form&gt;</code> 元素，它是用来收集信息的。</p><p><code>&lt;form&gt;</code> 元素有一个开头的 <code>&lt;form&gt;</code> 标签和结尾的 <code>&lt;/form&gt;</code> 标签。</p><pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;meta http-equiv="X-UA-Compatible" content="IE=edge"&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
    &lt;title&gt;Web form&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;form&gt;
        
    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre><p><code>&lt;form&gt;</code> 元素有两个属性：</p><ul><li><code>action</code> 属性，它指定了你希望数据被发送和处理的 URL。</li><li><code>method</code> 属性，接受两个 HTTP 动词中的一个作为值，即 <code>GET</code> 或 <code>POST</code>。如果没有 <code>method</code> 属性，则默认使用 <code>GET</code> 方法。</li></ul><pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;meta http-equiv="X-UA-Compatible" content="IE=edge"&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
    &lt;title&gt;Web form&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;form action="/url" method="GET"&gt;

    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre><p>然而，仅此一项并不收集任何用户输入。</p><h2 id="html-input-">HTML input 元素是什么</h2><p><code>&lt;input&gt;</code> 元素最常用于收集和检索 web 表单中的用户数据。</p><p>它是用户输入数据的地方。</p><p>它被嵌套在 <code>&lt;form&gt;</code> 元素内部，是一个自闭合元素。这意味着它不需要一个结束标签。（关闭标签有一个正斜杠，<code>&lt;/&gt;</code>）</p><p>你用它来创建不同风格的输入字段或<em>表单输入控件</em>，供用户输入各种不同的信息。</p><p>它可以创建文本字段、电子邮件字段、密码字段、复选框、单选按钮、下拉菜单、提交按钮，从用户的计算机中选择和上传文件和图像的能力，以及更多。</p><p>确定 input 字段或表单输入控件类型的方法是设置 <code>type</code> 属性并为其赋值。</p><p><code>&lt;input&gt;</code> 的语法是这样的：</p><pre><code class="language-html">&lt;input type="value"&gt; &lt;!-- the value of the type attribute determines the style of input field --&gt;

</code></pre><p>例如，要创建一个允许用户上传文件的字段，<code>&lt;input&gt;</code> 元素是这样的：</p><pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;meta http-equiv="X-UA-Compatible" content="IE=edge"&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
    &lt;title&gt;Web form&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;form action="/url" method="GET"&gt;
        &lt;input type="file"&gt;
    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre><p><code>type</code> 属性决定了该 <code>input</code> 元素可以接受什么样的数据。</p><h2 id="-html-">如何创建一个 HTML 文本输入框</h2><p>如果不指定 <code>input</code> 的 <code>type</code> 属性，其默认值是<strong>文本</strong>。所以文本输入是最常见的输入样式。</p><p><code>&lt;input type="text"&gt;</code> 创建了一个单行文本输入框，用户可以在这里输入任何文本。</p><pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;meta http-equiv="X-UA-Compatible" content="IE=edge"&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
    &lt;title&gt;Web form&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;form action="/url" method="GET"&gt;
        &lt;p&gt;Please enter some text below:&lt;/p&gt;
        &lt;input type="text"&gt;
    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre><p>当你在浏览器中查看该页面时，你可以看到创建了一个单行文本输入字段：</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2022/01/Screenshot-2022-01-09-at-5.52.22-PM.png" class="kg-image" alt="Screenshot-2022-01-09-at-5.52.22-PM" width="600" height="400" loading="lazy"></figure><h3 id="-">如何在文本字段中添加占位符文本</h3><p>占位符文本，也叫填充文本，是一种提示的方式，给用户一个提示，告诉他们需要在表单中填写什么样的信息。它还可以在用户开始输入之前提供一个默认值。</p><pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;meta http-equiv="X-UA-Compatible" content="IE=edge"&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
    &lt;title&gt;Web form&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;form action="/url" method="GET"&gt;
        &lt;p&gt;Please enter your first and last name:&lt;/p&gt;
        &lt;input type="text" placeholder="John"&gt;
        &lt;input type="text" placeholder="Doe"&gt;
    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre><p>上面代码的结果如下：</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2022/01/Screenshot-2022-01-09-at-6.09.59-PM.png" class="kg-image" alt="Screenshot-2022-01-09-at-6.09.59-PM" width="600" height="400" loading="lazy"></figure><h3 id="-name-">文本字段中 name 属性的重要性</h3><p>当提交表单并将其发送到服务器时，服务器需要区分它所收集的不同种类的提交数据。</p><p>例如，它需要知道哪个是用户名、哪个是密码、哪个是电子邮件地址。</p><p>这意味着每个文本字段都需要一个 <code>name</code> 属性和一个值，以使提交的数据类型更加清晰。</p><p>例如，你可以用下面的方法来提示某人在一个文本字段中输入他们的全名：</p><pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;meta http-equiv="X-UA-Compatible" content="IE=edge"&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
    &lt;title&gt;Web form&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;form action="/url" method="GET"&gt;
        &lt;p&gt;Please enter your full name:&lt;/p&gt;
        &lt;input type="text" name="name" placeholder="John Doe"&gt;
    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2022/01/Screenshot-2022-01-09-at-6.28.10-PM.png" class="kg-image" alt="Screenshot-2022-01-09-at-6.28.10-PM" width="600" height="400" loading="lazy"></figure><p>假设用户在文本字段中输入了 “John Bexley” 这个名字。然后，这将成为 <code>name</code> 属性的值。</p><p>如前所述，表单中的数据是以名-值对的形式发送的。在这种情况下，服务器会知道用户的 <code>name</code> 是 <code>John Bexley</code>，具体来说，就是 <code>name=John Bexley</code>。</p><p>再举一个例子：</p><pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;meta http-equiv="X-UA-Compatible" content="IE=edge"&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
    &lt;title&gt;Web form&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;form action="/url" method="GET"&gt;
        &lt;p&gt;Please enter your first  name:&lt;/p&gt;
        &lt;input type="text" name="first_name" placeholder="John"&gt;
        &lt;p&gt;Please enter your last  name:&lt;/p&gt;
        &lt;input type="text" name="last_name" placeholder="Doe"&gt;
    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre><p>上面的代码有两个独立的文本字段，供用户分别输入他们的名字和姓氏。</p><p>如果他们输入 “John” 作为名字，发送到服务器的名-值对将是 <code>first_name=John</code>。</p><p>如果他们输入 “Bexley” 作为姓氏，发送到服务器的名-值对将是 <code>last_name=Bexley</code>。</p><h3 id="--1">如何使文本信息是必填的</h3><p>你可以使某些字段成为必填项，需要用户填写。</p><p>HTML5 引入了客户端验证功能。</p><p>这是一个功能，如果用户没有填写必要的字段或没有正确输入信息，就会显示一条信息。这也意味着他们将无法提交表单。</p><p>为了启用这一功能，你需要做的就是给 <code>&lt;input&gt;</code> 元素添加 <code>required</code> 属性。这个属性不需要一个值。</p><p>请记住，在向 <code>&lt;input&gt;</code> 元素添加多个属性时，你不必按照一定的顺序添加元素。</p><pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;meta http-equiv="X-UA-Compatible" content="IE=edge"&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
    &lt;title&gt;Web form&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;form action="/url" method="GET"&gt;
        &lt;p&gt;Please enter your first  and last name:&lt;/p&gt;
        &lt;input type="text" name="first_name" placeholder="John" required&gt;
        &lt;input type="text" name="last_name" placeholder="Doe" required&gt;
        &lt;button type="submit"&gt;Submit&lt;/button&gt;  
    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre><p>看看如果一个用户没有填写其中一个字段会发生什么：</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2022/01/Screenshot-2022-01-09-at-6.59.44-PM.png" class="kg-image" alt="Screenshot-2022-01-09-at-6.59.44-PM" width="600" height="400" loading="lazy"></figure><p>如果用户没有填写所需的字段，就会出现一条信息，用户将无法提交表单。</p><h3 id="--2">如何设置文本框中的最小和最大字符数</h3><p>你可以指定用户在一个文本字段中可以输入的最小和最大字符数。</p><p>要创建一个最小字符数，请使用 <code>minlength</code> 属性。</p><p>例如，你可以让用户的用户名<em>至少</em>有三个字符长：</p><pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;meta http-equiv="X-UA-Compatible" content="IE=edge"&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
    &lt;title&gt;Web form&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;form action="/url" method="GET"&gt;
        &lt;p&gt;Please enter your username&lt;/p&gt;
        &lt;input type="text" name="username" minlength="3" required&gt;
        &lt;button type="submit"&gt;Submit&lt;/button&gt;  
    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre><p>如果用户名短于三个字符，用户将无法提交表单：</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2022/01/Screenshot-2022-01-10-at-4.04.00-PM.png" class="kg-image" alt="Screenshot-2022-01-10-at-4.04.00-PM" width="600" height="400" loading="lazy"></figure><p>要限制用户在一个文本字段中输入的字符数，可以使用 <code>maxlength</code> 属性。</p><p>一个结合 <code>minlength</code> 和 <code>maxlength</code> 属性的例子是这样的：</p><pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;meta http-equiv="X-UA-Compatible" content="IE=edge"&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
    &lt;title&gt;Web form&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;form action="/url" method="GET"&gt;
        &lt;p&gt;Please enter your username&lt;/p&gt;
        &lt;input type="text" name="username" minlength="3" maxlength="20" required&gt;
        &lt;button type="submit"&gt;Submit&lt;/button&gt;  
    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre><p>在上面的例子中，一个用户的用户名必须至少有 3 个字符，并且不超过 20 个字符。</p><h3 id="-label-">如何使用 label 元素</h3><p>到目前为止，我一直在使用 <code>&lt;p&gt;</code> 元素在文本框前写一些文字，以这种方式提示用户，让他们知道他们需要输入什么。</p><p>但这不是最佳实践。</p><p>每个表单控件，在这里是每个文本字段，都应该有自己的 <code>&lt;label&gt;</code> 元素。</p><p>这使得使用屏幕阅读器等辅助技术的视力障碍用户能够访问该表单。</p><p>一种方法是将任何介绍性文本和 <code>&lt;input type="text"&gt;</code> 嵌套在一个 <code>&lt;label&gt;</code> 元素中，像这样：</p><pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;meta http-equiv="X-UA-Compatible" content="IE=edge"&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
    &lt;title&gt;Web form&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;form action="/url" method="GET"&gt;
        &lt;label&gt;
            Please enter your username
            &lt;input type="text" name="username" minlength="3" maxlength="20" required&gt;
        &lt;/label&gt;
        &lt;button type="submit"&gt;Submit&lt;/button&gt;  
    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2022/01/Screenshot-2022-01-10-at-4.58.37-PM.png" class="kg-image" alt="Screenshot-2022-01-10-at-4.58.37-PM" width="600" height="400" loading="lazy"></figure><p>另一种使用 <code>&lt;label&gt;</code> 元素并获得相同结果的方法是将其与 <code>&lt;input&gt;</code> 元素分开。</p><p>在这种情况下，需要给 <code>&lt;label&gt;</code> 添加 <code>for</code> 属性，给 <code>&lt;input&gt;</code> 添加 <code>id</code> 属性，以便将两者联系在一起。</p><p><code>for</code> 的值将与 <code>id</code> 相同。</p><pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;meta http-equiv="X-UA-Compatible" content="IE=edge"&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
    &lt;title&gt;Web form&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;form action="/url" method="GET"&gt;
        &lt;label for="username"&gt; Please enter your username:&lt;/label&gt;
            &lt;input type="text" id="username" name="username" minlength="3" maxlength="20" required&gt;
        &lt;button type="submit"&gt;Submit&lt;/button&gt;  
    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre><h2 id="--3"><strong>总结</strong></h2><p>总而言之，要在 HTML 中创建一个文本输入字段，你至少需要：</p><ul><li>一个 <code>&lt;input&gt;</code> 元素，这通常是在一个 <code>&lt;form&gt;</code> 元素内。</li><li>将 <code>type</code> 属性的值设置为 <code>text</code>。这将创建一个单行文本输入框</li><li>不要忘记添加一个 <code>name</code> 属性。这可以识别每个被创建的表单控件的信息，使服务器更清楚地了解情况。</li></ul><p>要学习更多关于 HTML 和 CSS 的知识，请查看 freeCodeCamp 的<a href="https://www.freecodecamp.org/chinese/learn/2022/responsive-web-design/">响应式网页设计认证</a>。你可以学习交互式课程，并创建有趣的项目。</p><p>谢谢你阅读本文，happy coding！</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ 什么是 UTF-8？UTF-8 字符编码教程 ]]>
                </title>
                <description>
                    <![CDATA[ UTF-8 是一个字符编码系统。它可以让你将字符表示为 ASCII 文本，同时还允许使用国际字符，如中文字符。 截至 2020 年代中期，UTF-8 是最流行的编码系统之一。 要开始使用 UTF-8，你首先要熟悉基本的 ASCII 字符集。 什么是 ASCII 字符集 ASCII 使用 7 位代码来表示 128 个不同的字符。这些代码被分为 95 个可打印的字符，其中包括 26 个英文字母（A 到 Z，包括大写和小写）、10 个数字（0 到 9），以及各种标点符号和其他符号。 还有 33 个不可打印的字符，其中包括控制字符，如回车和换行，以及其他各种用于格式化文本的字符。 UTF-8 和 ASCII 有什么区别 UTF-8 扩展了 ASCII 字符集，使用 8 位代码，允许多达 256 个不同的字符。 这意味着 UTF-8 可以表示所有可打印的 ASCII 字符，以及不可打印的字符。 ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/what-is-utf-8-character-encoding/</link>
                <guid isPermaLink="false">63bba4a281727e0763145f7d</guid>
                
                    <category>
                        <![CDATA[ HTML ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Miya Liu ]]>
                </dc:creator>
                <pubDate>Wed, 04 Jan 2023 05:22:00 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2023/01/brett-jordan-M9NVqELEtHU-unsplash--1-.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>原文：</strong> <a href="https://www.freecodecamp.org/news/what-is-utf-8-character-encoding/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">What is UTF-8? UTF-8 Character Encoding Tutorial</a>
      </p><p>UTF-8 是一个字符编码系统。它可以让你将字符表示为 ASCII 文本，同时还允许使用国际字符，如中文字符。</p><p>截至 2020 年代中期，UTF-8 是最流行的编码系统之一。</p><p>要开始使用 UTF-8，你首先要熟悉基本的 ASCII 字符集。</p><h3 id="-ascii-">什么是 ASCII 字符集</h3><p>ASCII 使用 7 位代码来表示 128 个不同的字符。这些代码被分为 95 个可打印的字符，其中包括 26 个英文字母（A 到 Z，包括大写和小写）、10 个数字（0 到 9），以及各种标点符号和其他符号。</p><p>还有 33 个不可打印的字符，其中包括控制字符，如回车和换行，以及其他各种用于格式化文本的字符。</p><h3 id="utf-8-ascii-">UTF-8 和 ASCII 有什么区别</h3><p>UTF-8 扩展了 ASCII 字符集，使用 8 位代码，允许多达 256 个不同的字符。</p><p>这意味着 UTF-8 可以表示所有可打印的 ASCII 字符，以及不可打印的字符。</p><p>UTF-8 还包括各种额外的国际字符，如中文字符和阿拉伯字符。</p><h2 id="-utf-8-html-utf-8-">如何在你的网页中使用 UTF-8 - HTML UTF-8 实例</h2><p>现在是最简单的部分。你实际上不需要知道它是如何工作的（尽管我一会儿会告诉你）。你可以在你的 HTML 代码中配置 UTF-8 字符编码，只需在代码的 <code>&lt;head&gt;</code> 部分写上一行 HTML：</p><pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;meta charset="utf-8"&gt;
&lt;/head&gt;
&lt;/html&gt;
</code></pre><p>说完这些，让我解释一下 UTF-8 是如何工作的，以及为什么它是一个出色的编码方案。</p><h2 id="utf-8-">UTF-8 编码是如何工作的，以及每个字符使用的存储量是多少</h2><p>当用 UTF-8 表示字符时，每个代码都由一个或多个字节的序列来表示。使用的字节数取决于该字符所代表的码位。下面是使用范围的细分：</p><ul><li>在 ASCII 范围内（0-127）的代码由一个字节表示</li><li>（128-2047）范围内的码位由两个字节表示</li><li>（2048-65535）范围内的代码点由三个字节表示</li><li>（65536-1114111）范围内的代码由四个字节表示。（这似乎是很多可能的字符，但请记住，仅在中文中，就有数 10 万个字符。）</li></ul><p>UTF-8 序列的第一个字节被称为 “leader byte”。leader byte 提供了关于序列中有多少个字节的信息，以及字符的码位值是什么。</p><p>单字节序列的 leader byte 总是在（0-127）范围内。两字节序列的 leader byte 在（194-223）范围内。三字节序列的 leader byte 在（224-239）范围内。四字节序列的 leader byte 在（240-247）范围内。</p><p>序列中剩余的字节被称为 “trailing bytes”。两字节序列的 trailing bytes 的范围是（128-191）。三字节序列的 trailing bytes 的范围是（128-191）。而四字节序列的 trailing bytes 在（128-191）范围内。</p><p>你可以通过查看 leader bytes 和 trailing bytes 来计算一个字符的码位值。对于一个单字节的序列，其码位值等于 leader bytes 的值。</p><p>对于一个两字节的序列，码位值等于 ((leader byte - 194) * 64) + (trailing byte - 128)。</p><p>对于一个三字节的序列，码位值等于 ((leader byte - 224) * 4096) + ((trailing byte1 - 128) * 64) + (trailing byte2 - 128)。</p><p>对于一个四字节的序列，码位值等于 ((leader byte - 240) * 262144) + ((trailing byte1 - 128) * 4096) + ((trailing byte2 - 128) * 64) + (trailing byte3 - 128)。</p><h2 id="utf-8--1">UTF-8 是一个不错的编码选择</h2><p>UTF-8 是一个超级有效的编码系统。它可以代表广泛的字符，同时仍然与 ASCII 兼容。这使得它成为国际化软件中的一个不错选择。</p><p>我希望这篇文章对你有帮助。如果你想学习更多关于编程和技术的知识，可以查看 <a href="https://www.freecodecamp.org/chinese/learn">freeCodeCamp 的核心编程课程</a>。它是免费的。</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ HTML 中的 DOCTYPE 声明是什么？ ]]>
                </title>
                <description>
                    <![CDATA[ HTML 文档类型声明，也被称为 DOCTYPE，是每个 HTML 或 XHTML 文档中需要的第一行代码。DOCTYPE 声明是给 Web 浏览器的一个指令，说明网页是用什么版本的 HTML 写的。这可以确保不同的网络浏览器对网页的解析方式是相同的。 在 HTML 4.01 中，DOCTYPE 声明是指文档类型定义（DTD）。DTD 定义了一个 XML 文档的结构和元素。因为 HTML 4.01 是基于标准通用标记语言（SGML）的，所以在 DOCTYPE 声明中提到 DTD 是必要的。 此外，HTML 4.01 的 doctype 要求声明 strict、transitional 或 frameset  DTD，每一种都有不同的使用情况，如下所述。  * 严格型 DTD：用于排除某些属性和元素的网页——W3C 希望随着 CSS 支持的增加而逐步淘汰这些属性和元素。  * 过渡型 DTD：用于包括某些属性和元素的网页——W3C 希望随着 CSS ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/what-is-the-doctype-declaration-in-html/</link>
                <guid isPermaLink="false">637b5696206aea0762969a85</guid>
                
                    <category>
                        <![CDATA[ HTML ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Chengjun.L ]]>
                </dc:creator>
                <pubDate>Wed, 07 Dec 2022 04:19:00 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2022/11/5f9c9e63740569d1a4ca3cda.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>原文：</strong> <a href="https://www.freecodecamp.org/news/what-is-the-doctype-declaration-in-html/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">What is the DOCTYPE Declaration in HTML?</a>
      </p><p>HTML 文档类型声明，也被称为 <code>DOCTYPE</code>，是每个 HTML 或 XHTML 文档中需要的第一行代码。<code>DOCTYPE</code> 声明是给 Web 浏览器的一个指令，说明网页是用什么版本的 HTML 写的。这可以确保不同的网络浏览器对网页的解析方式是相同的。</p><p>在 HTML 4.01 中，<code>DOCTYPE</code> 声明是指文档类型定义（DTD）。DTD 定义了一个 XML 文档的结构和元素。因为 HTML 4.01 是基于标准通用标记语言（SGML）的，所以在 <code>DOCTYPE</code> 声明中提到 DTD 是必要的。</p><p>此外，HTML 4.01 的 doctype 要求声明 <code>strict</code>、<code>transitional</code> 或 <code>frameset</code> &nbsp;DTD，每一种都有不同的使用情况，如下所述。</p><ul><li>严格型 DTD：用于排除某些属性和元素的网页——W3C 希望随着 CSS 支持的增加而逐步淘汰这些属性和元素。</li><li>过渡型 DTD：用于包括某些属性和元素的网页——W3C 希望随着 CSS 支持的增加而逐步淘汰这些属性和元素。</li><li>框架型 DTD：用于带有框架的网页。</li></ul><p>相比之下，HTML5 <code>DOCTYPE</code> 的声明要简单得多：它不再需要引用 DTD，因为它不再基于 SGML。请看下面的例子来比较 HTML4.01 和 HTML5 <code>DOCTYPE</code>。</p><h3 id="-">示例</h3><p>HTML5 及以后的 doctype 语法：</p><pre><code class="language-html">&lt;!DOCTYPE html&gt;</code></pre><p>严格型 HTML 4.01 的 doctype 语法：</p><pre><code class="language-html">&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"&gt;</code></pre><p>过渡型 HTML 4.01 的 doctype 语法：</p><pre><code class="language-html">&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"&gt;</code></pre><p>框架型 HTML 4.01 的 doctype 语法：</p><pre><code class="language-html">&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd"&gt;</code></pre><h2 id="--1"><strong><strong><strong>历史</strong></strong></strong></h2><p>在 HTML 的形成期，web 标准还没有达成一致。浏览器供应商会以他们想要的方式创建新的特性。人们很少关注竞争性的浏览器。</p><p>其结果是，web 开发者不得不选择一个浏览器来开发他们的网站。这意味着网站在不支持的浏览器中无法很好地呈现。这种情况不能再继续下去了。</p><p>W3C（万维网联盟）制定了一套 web 标准来处理这种情况。所有的浏览器供应商和 web 开发人员都应该遵守这些标准。这将确保网站在不同的浏览器上都能很好地呈现。</p><p>该标准所要求的变化与一些现有的做法有很大的不同。遵循这些标准会破坏现有的不符合标准的网站。</p><p>为了解决这个问题，供应商开始在他们的浏览器中设置渲染模式。web 开发者需要在 HTML 文档的顶部添加一个 doctype 声明。doctype 声明将告诉浏览器对该文档使用何种渲染模式。</p><p>各个浏览器通常有三种不同的渲染模式：</p><ul><li>完全标准模式是根据 W3C 网络标准来渲染页面。</li><li>怪异模式以不符合标准的方式渲染页面。</li><li>准标准模式接近于完全标准模式，但具有支持少量怪异的特性。</li></ul><p>在现代的 HTML5 时代，web 标准在所有主要的浏览器中都得到了充分的实施。网站一般都是以符合标准的方式开发的。正因为如此，HTML5 doctype 声明的存在只是为了告诉浏览器以完全标准模式来渲染文档。</p><h2 id="--2">使用</h2><p>除了注释之外，doctype 声明必须是 HTML 文档中的第一行代码，如果需要，注释可以放在前面。对于现代 HTML5 文档，doctype 声明应该如下：</p><p><code>&lt;!DOCTYPE html&gt;</code></p><h4 id="--3">更多信息</h4><p>虽然不再普遍使用，但还有几个其他的 doctype 声明类型来自以前的 HTML 版本。也有专门针对 XML 文档的版本。要想了解更多关于这些类型的信息，并查看每种类型的代码示例，请看<a href="https://en.wikipedia.org/wiki/Document_type_declaration">维基百科的文章</a>。</p><p><a href="https://www.w3.org/QA/Tips/Doctype">W3 上的解释</a></p><p><a href="https://developer.mozilla.org/en-US/docs/Glossary/Doctype">MDN 词汇</a></p><p><a href="https://www.w3schools.com/tags/tag_doctype.asp">W3Schools</a></p><p><a href="https://developer.mozilla.org/en-US/docs/Quirks_Mode_and_Standards_Mode">关于怪异模式和标准模式的解释</a></p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ 语义化 HTML 指南——div 的十种替换方案 ]]>
                </title>
                <description>
                    <![CDATA[ 如果你的 HTML 布局是这个样子，请举手： <body>   <div class="header" id="site-header">     <div class="site-nav">       <ul>         <li><a href="/">Home</a></li>         <li><a href="/">About</a></li>         ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/semantic-html-alternatives-to-using-divs/</link>
                <guid isPermaLink="false">636bb2d6c8777b07d5fd1b6a</guid>
                
                    <category>
                        <![CDATA[ 无障碍 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ HTML ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ PapayaHUANG ]]>
                </dc:creator>
                <pubDate>Wed, 09 Nov 2022 04:19:00 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2022/11/root-font-size-article-image.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>原文：</strong> <a href="https://www.freecodecamp.org/news/semantic-html-alternatives-to-using-divs/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">Semantic HTML Guide – 10 Alternatives to Using divs</a>
      </p><!--kg-card-begin: markdown--><p>如果你的 HTML 布局是这个样子，请举手：</p>
<pre><code class="language-html">&lt;body&gt;
  &lt;div class="header" id="site-header"&gt;
    &lt;div class="site-nav"&gt;
      &lt;ul&gt;
        &lt;li&gt;&lt;a href="/"&gt;Home&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href="/"&gt;About&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href="/"&gt;Contact&lt;/a&gt;&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="content-wrap"&gt;
    &lt;div class="intro"&gt;
      This is the introduction to the site, which is full of divs.
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="container"&gt;&lt;/div&gt;
&lt;/body&gt;
</code></pre>
<p>大部分人在搭建 HTML 布局的时候会默认使用 <code>&lt;div&gt;</code> 元素。大多数人会把精力放在更有趣的 CSS 或者 JavaScript。</p>
<p>使用 <code>&lt;div&gt;</code> 元素在搭建页面的时候很简单，但是在后期会造成一些麻烦。</p>
<h2 id="div">仅使用<code>div</code>带来的问题</h2>
<p>使用 <code>&lt;div&gt;</code> 元素本身并没有什么问题。存在即合理。</p>
<p>但大量地使用 DIV 会给你和你的合作伙伴带来麻烦。</p>
<h3 id="">易读性问题</h3>
<p>如果你尝试去看别人的代码，或者是几个月后回看自己的代码，如果整个页面只有 <code>&lt;div&gt;</code>元素，很难快速浏览。</p>
<p>你得花费更多地时间去解构页面，这或许会成为你效率的绊脚石。仅是寻找某一个代码块的结束 <code>&lt;/div&gt;</code> 标签都会花费你大量时间。</p>
<h3 id="">无障碍问题</h3>
<p>遵循无障碍（a11y）原则是实践，不单是考虑颜色、对比和字幕。根据 WHO（联合国卫生组织）的统计结果：全世界约有 2.85 亿人口遭遇视觉损伤，其中 0.39 亿失明，2.46 亿视力低下。</p>
<p>这就是 HTML 应该无障碍的原因，也就是使用语义化代码。</p>
<p>屏幕阅读器需要通过上下文来判断网页的准确信息。 对于屏幕阅读器来说，<code>&lt;div&gt;</code>和<code>&lt;span&gt;</code>这类元素没有任何意义； 而<code>&lt;form&gt;</code>和 <code>&lt;button&gt;</code>这类语义化的元素更好解析。</p>
<h3 id="">一致性问题</h3>
<p>在团队工作中，如果你知道你即将在项目中担任什么角色，你的工作效率会更高，代码中的问题也会越少。</p>
<p>把使用语义化 HTML 设置为一个标准可以使任何刚加入的人马上了解网页布局。</p>
<p>另外，当你开始使用 CSS 来调整 HTML 样式的时候，你会发现语义化的 HTML 的元素更容易被选定。</p>
<h3 id="seo">SEO 问题</h3>
<p>使用语义化标记时，搜索引擎会将这些内容视为重要的关键字，以此来提高页面的搜索排名。 <a href="https://developer.mozilla.org/en-US/docs/Glossary/Semantics">(MDN 网页文档)</a></p>
<p>何为语义化 HTML？</p>
<p>我找到最<a href="https://www.w3schools.com/html/html5_semantic_elements.asp">清晰的定义</a> 是：</p>
<blockquote>
<p>语义元素清楚地向浏览器和开发人员描述了它的含义。</p>
</blockquote>
<p>使用语义化 HTML 带来的改变很像这样的场景：当你指向天空一个物品大呼：“快看！有一个物品”和“快看！有一架飞机”。</p>
<p>清晰描述日常物品使得日常交流更加容易，而语义化 HTML 使得读取代码更加容易。</p>
<p>实际上，语义化 HTML 已经被当作 <a href="https://html.spec.whatwg.org/multipage/grouping-content.html#the-div-element">HTML5 标准</a>：</p>
<blockquote>
<p>鼓励开发者将 <a href="https://html.spec.whatwg.org/multipage/grouping-content.html#the-div-element">div</a> 元素作为备选方案，当实在没有别的元素可以使用的时候再使用。使用比 <code>div</code> 元素更适合的元素可以使网页的无障碍性更好，使开发者更易维护代码。</p>
</blockquote>
<p>举一个例子，哪一个更方便阅读：</p>
<pre><code class="language-html">&lt;div class="quote" id="twain-quote"&gt;
  "Get your facts first, then you can distort them as you please." – Mark Twain
&lt;/div&gt;
</code></pre>
<p>或者</p>
<pre><code class="language-html">&lt;blockquote&gt;
  "Get your facts first, then you can distort them as you please." – Mark Twain
&lt;/blockquote&gt;
</code></pre>
<p>在上面两个例子中，我们看到了 <code>&lt;blockquote&gt;</code> 元素，我们很容易就理解到元素内的文字应该被当作引用来处理格式。</p>
<p>如果使用<code>div</code>可能需要进一步判断，但使用语义化 HTML 总不会错。</p>
<h2 id="htmldiv">HTML 中<code>div</code>的替换元素</h2>
<p>让我们来看看一些常用的<code>div</code> 替换元素。你很有可能见过这些元素，我们将在这里讲解它们存在的原因以及如何使用。</p>
<h3 id="nav"><nav>元素</nav></h3>
<pre><code class="language-html">&lt;nav&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href="/"&gt;Home&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="/"&gt;About&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="/"&gt;Contact&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/nav&gt;
</code></pre>
<p>nav 元素正如其名，是用来标记一系列导航连接的元素。</p>
<p>如上文所述，这个标记可以帮助屏幕阅读器判断是否现在就展示所属内容。<code>nav</code> 元素的最佳实践是 HTML 文档中的导航链接代码块。</p>
<h3 id="main"><main> 元素</main></h3>
<pre><code class="language-html">&lt;main&gt;
  &lt;h1&gt;The Godfather of All Content&lt;/h1&gt;
  &lt;h2&gt;The Wedding&lt;/h2&gt;
  &lt;p&gt;
    Why did you go to the police? Why didn't you come to me first? Vito, how do
    you like my little angel? Isn't she beautiful? Only don't tell me you're
    innocent. Because it insults my intelligence and makes me very angry. I see
    you took the name of the town. What was your father's name? The hotel, the
    casino. The Corleone Family wants to buy you out.
  &lt;/p&gt;
&lt;/main&gt;
</code></pre>
<p>和 <code>&lt;nav&gt;</code>类似，这个元素也正如其名（语义化派上了用场）。该元素将页面或者文档的主要内容打包成一个块级元素。main 元素位于两个<code>&lt;body&gt;</code>标签之间。</p>
<h3 id="section"><section> 元素</section></h3>
<pre><code class="language-html">&lt;section&gt;
  &lt;h1&gt;The Best Sandwich Ever&lt;/h1&gt;
&lt;/section&gt;
&lt;section&gt;
  &lt;p&gt;
    The best sandwich is a mutton, lettuce and tomato, where the mutton is nice
    and lean. It's so perky, I love that.
  &lt;/p&gt;
&lt;/section&gt;
</code></pre>
<p><code>&lt;section&gt;</code>元素是取代<code>div</code>来区分不同内容绝佳的例子。</p>
<p>在上面的例子中，我们将一段介绍和段落开头区分成两个 section，这样和<code>&lt;div&gt;</code>类相比在 CSS 文档中就更容易找到这些 section。</p>
<h3 id="header"><header> 元素</header></h3>
<pre><code class="language-html">&lt;header&gt;
  &lt;img src="/" id="logo" /&gt;
&lt;/header&gt;
</code></pre>
<p><code>&lt;header&gt;</code> 元素和<code>&lt;head&gt;</code> 不同，你可以在文档内多次使用。</p>
<p>例如，你可以使用一对<code>&lt;header&gt;</code> 元素来放置一个 logo，以及另一组对 header 来介绍特定的内容，如 article（之后会详细说明）。</p>
<h3 id="footer"><footer> 元素</footer></h3>
<pre><code class="language-html">&lt;footer&gt;
  &lt;p&gt;© 2021 All rights reserved. Don't steal.&lt;/p&gt;
  &lt;p&gt;Contact: &lt;a href="mailto:jiffy@jiffysites.com"&gt;Email Jiffy!&lt;/a&gt;&lt;/p&gt;
&lt;/footer&gt;
</code></pre>
<p>和 <code>&lt;header&gt;</code> 元素一样，你可以在 HTML 文档中的任意地方使用 <code>&lt;footer&gt;</code> 元素。</p>
<p><code>&lt;footer&gt;</code> 的典型案例是展示版权和作者信息，也可以使用 footer 元素来结束 <code>&lt;section&gt;</code> 元素。</p>
<h3 id="div">一些不那么常见的 <code>div</code>替换</h3>
<p>还有一些元素你可能见过，或者只见过一两次。但是当你需要的时候，它们很有用，学习它们可以使得你的代码的易读性更好。</p>
<h3 id="aside"><aside> 元素</aside></h3>
<pre><code class="language-html">&lt;p&gt;
  My favorite TV show of all time is The Muppet Show. It's sweet, funny and
  brilliant.
&lt;/p&gt;
&lt;aside&gt;
  &lt;h3&gt;The Muppet Show&lt;/h3&gt;
  &lt;p&gt;The Muppet Show was created by Jim Henson and aired from 1976 – 1981.&lt;/p&gt;
&lt;/aside&gt;
</code></pre>
<p>在影视和戏剧作品中，aside 是一种戏剧手法，角色会跳脱出主要的对话，和观众进行交流。</p>
<p>我们在 HTML 中也可以这样使用 </p><aside> 元素。我们对一个内容做注解，注解和主题内容区分。我们可以把它放置在侧边栏。<p></p>
<h3 id="code"><code> 元素</code></h3><code>
<pre><code class="language-html">&lt;p&gt;
  You can use this for a piece of code such as:
  &lt;code class="gray-code"&gt;const muppetFrog = 'Kermit'&lt;/code&gt;, which looks
  different from the other text.
&lt;/p&gt;
</code></pre>
<p>如果想要将代码和普通文本区分开来，可以使用 <code>&lt;code&gt;</code> 元素。上面示例在浏览器的渲染结果（添加了一点 CSS 样式）如下：</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/07/code-display.png" alt="code-display" width="600" height="400" loading="lazy"></p>
<h3 id="article"><article> 元素</article></h3>
<pre><code class="language-html">&lt;article class="all-muppets"&gt;
  &lt;h1&gt;Muppets&lt;/h1&gt;
  &lt;article class="kermit"&gt;
    &lt;p&gt;Kermit is the Muppet leader.&lt;/p&gt;
  &lt;/article&gt;
  &lt;article class="fozzy"&gt;
    &lt;p&gt;Fozzy is a stand-up bear.&lt;/p&gt;
  &lt;/article&gt;
  &lt;article class="piggy"&gt;
    &lt;p&gt;Don't mess with Miss Piggy.&lt;/p&gt;
  &lt;/article&gt;
&lt;/article&gt;
</code></pre>
<p><code>&lt;article&gt;</code> 元素也是用来和其他元素区分内容的。</p>
<p><code>&lt;article&gt;</code>自成一体，和主内容区分开来。使用这个元素可以更容易使用 CSS 将它与页面其他内容区分开来。</p>
<h3 id="blockquote"><blockquote> 元素</blockquote></h3>
<p><code>&lt;blockquote&gt;</code> 简单明了，将引文和其他文本区分开来，如上文所示。</p>
<h3 id="mark"><mark> 元素</mark></h3>
<pre><code class="language-html">&lt;p&gt;
  This is a sentence about the best Muppet ever, which happens to be
  &lt;mark&gt;Pepe the King Prawn&lt;/mark&gt;.
&lt;/p&gt;
</code></pre>
<p><code>&lt;mark&gt;</code> 元素不仅可以使文本高亮，也可以使文档内容更易被理解，如下：</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/07/mark-display.png" alt="mark-display" width="600" height="400" loading="lazy"></p>
<p>请在你的代码中使用这些<code>div</code>替换元素，提高你的代码的易读性。</p>
<h2 id="">总结</h2>
<p>以上只是十个 <code>div</code> 的替换元素，在 HTML 还有另一些语义化元素。</p>
<p>我们不可能在一个文档中把它们全都用了，也不需要记住这一百来个元素。 需要的时候你可以查看 MDN 文档： <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element">HTML 元素参考</a>。</p>
<p>编写语义化 HTML 是一个好习惯，越早开始越好。它提高了易读性、SEO，同时也不要忘了那些视觉障碍的人，他们会非常感谢你的体贴。</p>
<!--kg-card-end: markdown--></code></aside> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ HTML 表单——输入类型和提交按钮示例 ]]>
                </title>
                <description>
                    <![CDATA[ 表单是网络中最重要的部分之一。没有它们，就不会有收集数据、搜索资源或注册接收有价值信息的简便方法。 你可以用 HTML form 元素在网站上嵌入表单。在 form 元素内部，有几个嵌套输入。这些输入也被称为表单控件。 在本教程中，我们将探讨 HTML form 元素，它所接受的各种输入类型，以及如何创建一个提交数据的按钮。 最后，你将知道表单是如何工作的，并且你将能够自信地制作它们。 基本的 HTML 表单语法 <form action="mywebsite.com" method="POST">     <!--Input of any type and textareas goes in here--> </form> HTML 表单输入类型 你使用 <input> 标签来创建 HTML 中的各种表单控件。它是一个内联元素，具有 type、name、minlength、maxlength、 placeholder 等等属性。每个属性都有特定的取值。 placeholder 属性很重要，因为它可以帮助用户在输入任何东西之前了解输入字段的目的。 有 20 种不同的输入 ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/html-form-input-type-and-submit-button-example/</link>
                <guid isPermaLink="false">6364ce2573e419079177bf44</guid>
                
                    <category>
                        <![CDATA[ HTML ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Chengjun.L ]]>
                </dc:creator>
                <pubDate>Fri, 04 Nov 2022 04:18:00 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2022/11/form-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>原文：</strong> <a href="https://www.freecodecamp.org/news/html-form-input-type-and-submit-button-example/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">HTML Form – Input Type and Submit Button Example</a>
      </p><p>表单是网络中最重要的部分之一。没有它们，就不会有收集数据、搜索资源或注册接收有价值信息的简便方法。</p><p>你可以用 HTML <code>form</code> 元素在网站上嵌入表单。在 <code>form</code> 元素内部，有几个嵌套输入。这些输入也被称为表单控件。</p><p>在本教程中，我们将探讨 HTML <code>form</code> 元素，它所接受的各种输入类型，以及如何创建一个提交数据的按钮。</p><p>最后，你将知道表单是如何工作的，并且你将能够自信地制作它们。</p><h2 id="-html-"><strong>基本的 HTML 表单语法</strong></h2><pre><code class="language-html">&lt;form action="mywebsite.com" method="POST"&gt;
    &lt;!--Input of any type and textareas goes in here--&gt;
&lt;/form&gt;
</code></pre><h2 id="html-"><strong>HTML 表单输入类型</strong></h2><p>你使用 <code>&lt;input&gt;</code> 标签来创建 HTML 中的各种表单控件。它是一个内联元素，具有 <code>type</code>、<code>name</code>、<code>minlength</code>、<code>maxlength</code>、<code>placeholder</code> 等等属性。每个属性都有特定的取值。</p><p><code>placeholder</code> 属性很重要，因为它可以帮助用户在输入任何东西之前了解输入字段的目的。</p><p>有 20 种不同的输入类型，我们将逐一看一下它们。</p><h3 id="-">文本类型</h3><p>这种类型的输入取值为“文本”，所以它创建了一个单行的文本输入。</p><pre><code class="language-html">&lt;input type="text" placeholder="Enter name" /&gt;
</code></pre><p>文本类型的输入看起来像下面的屏幕截图：</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/08/textInput.png" class="kg-image" alt="textInput" width="600" height="400" loading="lazy"></figure><h3 id="--1">密码类型</h3><p>顾名思义，一个密码类型的输入会创建一个密码。它对用户来说是自动不可见的，除非它被 JavaScript 所操纵。</p><pre><code class="language-html">&lt;input type="password" placeholder="Enter your password" /&gt;
</code></pre><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/08/passwordInput.png" class="kg-image" alt="passwordInput" width="600" height="400" loading="lazy"></figure><h3 id="--2">电子邮件类型</h3><p>电子邮件类型的输入定义了一个用于输入电子邮件地址的字段。</p><pre><code class="language-html">&lt;input type="email" placeholder="Enter your email" /&gt;
</code></pre><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/08/typeEmail.png" class="kg-image" alt="typeEmail" width="600" height="400" loading="lazy"></figure><h3 id="--3">数字类型</h3><p>这种类型的输入只允许用户插入数字。</p><pre><code class="language-html">&lt;input type="number" placeholder="Enter a number" /&gt;
</code></pre><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/08/numberInput.png" class="kg-image" alt="numberInput" width="600" height="400" loading="lazy"></figure><h3 id="--4">单选类型</h3><p>有时，用户需要从众多选项中挑选一个。一个类型属性设置为“单选”的输入字段让你做到这一点。</p><pre><code class="language-html"> &lt;input type="radio" /&gt;
</code></pre><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/08/typeRadio.png" class="kg-image" alt="typeRadio" width="600" height="400" loading="lazy"></figure><h3 id="--5">复选框类型</h3><p>所以，对于输入类型的单选，用户可以从众多的选项中挑选一个。如果你想让他们尽可能多地挑选选项呢？这就是类型属性设置为 <code>checkbox</code> 的输入的作用。</p><pre><code class="language-html">&lt;input type="checkbox" /&gt;
</code></pre><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/08/typeCheckbox.png" class="kg-image" alt="typeCheckbox" width="600" height="400" loading="lazy"></figure><h3 id="--6">提交类型</h3><p>你用这个类型来给表单添加一个提交按钮。当用户点击它时，它会自动提交表单。它需要一个 <code>value</code> 属性，定义出现在按钮内的文本。</p><pre><code class="language-html">&lt;input type="submit" value="Enter to Win" /&gt;
</code></pre><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/08/typeSubmit.png" class="kg-image" alt="typeSubmit" width="600" height="400" loading="lazy"></figure><h3 id="--7">按钮类型</h3><p>类型设置为 <code>button</code> 的输入会创建一个按钮，可以通过 JavaScript 的 <code>onClick</code> 事件监听器类型进行操作。它创建的按钮就像提交类型的输入一样，但例外的是，其值默认是空的，所以必须指定。</p><pre><code class="language-html">&lt;input type="button" value="Submit" /&gt;
</code></pre><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/08/typeButton.png" class="kg-image" alt="typeButton" width="600" height="400" loading="lazy"></figure><h3 id="--8">文件类型</h3><p>这定义了一个用于提交文件的字段。当用户点击它时，他们会被提示插入所需的文件类型，可能是图像、PDF、文档文件等。</p><pre><code class="language-html">&lt;input type="file" /&gt;
</code></pre><p>一个输入文件类型的结果看起来是这样的：</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/08/fileInput.png" class="kg-image" alt="fileInput" width="600" height="400" loading="lazy"></figure><h3 id="--9">颜色类型</h3><p>这是一个由 HTML5 引入的花式输入类型。通过它，用户可以提交他们最喜欢的颜色，黑色（#000000）是默认值，但可以通过将该值设置为所需的颜色来覆盖。</p><p>许多开发者将其作为一种技巧，以选择 RGB、HSL 和字母数字格式中可用的不同颜色色调。</p><pre><code class="language-html">&lt;input type="color" /&gt;
</code></pre><p>一个输入颜色类型的结果看起来是这样的：</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/08/colorInput.png" class="kg-image" alt="colorInput" width="600" height="400" loading="lazy"></figure><h3 id="--10">搜索类型</h3><p>搜索类型的输入定义了一个文本字段，就像文本的输入类型一样。但这一次它的唯一目的是搜索信息。它与文本类型的不同之处在于，一旦用户开始输入，就会出现一个取消按钮。</p><pre><code class="language-html">&lt;input type="search" /&gt;
</code></pre><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/08/typeSearch.png" class="kg-image" alt="typeSearch" width="600" height="400" loading="lazy"></figure><h3 id="url-"><strong>URL 类型</strong></h3><p>当输入标签的类型属性被设置为 URL 时，它会显示一个用户可以输入 URL 的区域。</p><pre><code class="language-html">&lt;input type="url" /&gt;
</code></pre><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/08/typeURL.png" class="kg-image" alt="typeURL" width="600" height="400" loading="lazy"></figure><h3 id="tel-"><strong>Tel 类型</strong></h3><p>输入类型为 tel，让你可以从用户那里收集电话号码。</p><pre><code class="language-html">&lt;input type="tel" /&gt;
</code></pre><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/08/typeTel.png" class="kg-image" alt="typeTel" width="600" height="400" loading="lazy"></figure><h3 id="--11"><strong>日期类型</strong></h3><p>你可能已经在一个网站上注册了，在那里你被要求提供某个事件的日期。该网站可能使用了一个类型值设置为日期的输入来实现这一目的。</p><pre><code class="language-html">&lt;input type="date" /&gt;
</code></pre><p>一个日期类型的输入是这样的：</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/08/dateInput.png" class="kg-image" alt="dateInput" width="600" height="400" loading="lazy"></figure><h3 id="--12">日期-本地类型</h3><p>这与日期类型输入的工作原理相同，但它也可以让用户选择一个具有特定时间的日期。</p><pre><code class="language-html">&lt;input type="datetime-local" /&gt;
</code></pre><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/08/datelocalInput.png" class="kg-image" alt="datelocalInput" width="600" height="400" loading="lazy"></figure><h3 id="--13">周类型</h3><p>输入类型为周，可以让用户选择一个特定的星期。</p><pre><code class="language-html">&lt;input type="week" /&gt;
</code></pre><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/08/weekInput.png" class="kg-image" alt="weekInput" width="600" height="400" loading="lazy"></figure><h3 id="--14"><strong>月类型</strong></h3><p>当用户点击它时，带有月份类型的输入会弹出月份供用户选择。</p><pre><code class="language-html">&lt;input type="month" /&gt;
</code></pre><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/08/monthInput.png" class="kg-image" alt="monthInput" width="600" height="400" loading="lazy"></figure><h3 id="textarea"><strong>Textarea</strong></h3><p>有的时候，用户需要填写多行文本，这在文本输入类型中是不合适的（因为它指定的是单行文本字段）。</p><p><code>textarea</code> 可以让用户这样做，因为它定义了多行的文本输入。它有自己的属性，如 <code>cols</code> 表示列的数量，<code>rows</code> 表示行的数量。</p><pre><code class="language-html">&lt;textarea cols="50" rows="20"&gt;&lt;/textarea&gt;
</code></pre><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/08/textarea.png" class="kg-image" alt="textarea" width="600" height="400" loading="lazy"></figure><h3 id="--15">多选</h3><p>这就像一个单选按钮和复选框的组合。它在页面中嵌入了两个元素——一个 <code>select</code> 元素和一个 <code>option</code>，后者总是嵌套在 <code>select</code> 元素中。</p><p>默认情况下，用户只能选择其中一个选项。但通过多重属性，你可以让用户选择一个以上的选项。</p><pre><code class="language-html">&lt;select&gt;
      &lt;option value="HTML"&gt;Select a Language&lt;/option&gt;
      &lt;option value="HTML"&gt;HTML&lt;/option&gt;
      &lt;option value="CSS"&gt;CSS&lt;/option&gt;
      &lt;option value="JavaScript"&gt;JavaScript&lt;/option&gt;
      &lt;option value="React"&gt;React&lt;/option&gt;
&lt;/select&gt;
</code></pre><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/08/selectDemo.gif" class="kg-image" alt="selectDemo" width="600" height="400" loading="lazy"></figure><h2 id="-html--1">如何给 HTML 输入加标签</h2><p>为表单控件指定标签是很重要的。当它们通过 <code>for</code> 属性和输入的 <code>id</code> 属性与输入字段正确连接时，用户就会更容易使用，因为他们可以直接点击标签本身来访问输入。</p><pre><code class="language-html">&lt;label for="name"&gt;Name&lt;/label&gt;
&lt;input type="text" id="name" /&gt; &lt;br /&gt;
&lt;label for="check"&gt;Agree with terms&lt;/label&gt;
&lt;input type="checkbox" id="check" /&gt;
</code></pre><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/08/labelDemo.gif" class="kg-image" alt="labelDemo" width="600" height="400" loading="lazy"></figure><h2 id="html--1">HTML 表单是如何工作的</h2><p>当用户填写表单并用提交按钮提交时，表单控件中的数据会通过 <code>GET</code> 或 <code>POST</code> HTTP 请求方法发送到服务器。</p><p>那么，服务器是如何指示的呢？表单元素需要一个 <code>action</code> 属性，它的值必须指定为服务器的 URL。它还需要一个 <code>method</code> 属性，在这里指定它用来向服务器传达数值的 HTTP 方法。</p><p>这个方法可以是 <code>GET</code> 或 <code>POST</code>。使用 <code>GET</code> 方法，当数据被提交时，用户输入的值在 URL 中是可见的。但是用 <code>POST</code> 方法，值是在 HTTP 头中发送的，所以这些值在 URL 中是不可见的。</p><p>如果表单中没有使用 <code>method</code> 属性，就会自动假定用户想使用 <code>GET</code> 方法，因为这是默认的。</p><p>那么，你应该在什么时候使用 <code>GET</code> 或 <code>POST</code> 方法？在提交非敏感数据或从服务器检索数据时使用 <code>GET</code> 方法（例如，在搜索期间），在提交文件或敏感数据时使用 <code>POST</code> 请求。</p><h2 id="--16">小项目：创建一个基本的联系表单</h2><p>让我们把我们所学到的关于表单的知识，用来制作一个简单的联系表单。我还会在这个过程中引入一些新的概念来完善这一切。</p><p>这是 HTML：</p><pre><code class="language-html">&lt;form action=example-server.com"&gt;
      &lt;fieldset&gt;
        &lt;legend&gt;Contact me&lt;/legend&gt;
        &lt;div class="form-control"&gt;
          &lt;label for="name"&gt;Name&lt;/label&gt;
          &lt;input type="name" id="name" placeholder="Enter your name" required /&gt;
        &lt;/div&gt;

        &lt;div class="form-control"&gt;
          &lt;label for="email"&gt;Email&lt;/label&gt;
          &lt;input
            type="email"
            id="email"
            placeholder="Enter your email"
            required
          /&gt;
        &lt;/div&gt;

        &lt;div class="form-control"&gt;
          &lt;label for="message"&gt;Message&lt;/label&gt;
          &lt;textarea
            id="message"
            cols="30"
            rows="10"
            placeholder="Enter your message"
            required
          &gt;&lt;/textarea&gt;
        &lt;/div&gt;
        &lt;input type="submit" value="Send" class="submit-btn" /&gt;
      &lt;/fieldset&gt;
&lt;/form&gt;
</code></pre><h4 id="-html--2"><strong>这段 HTML 代码中发生了什么？</strong></h4><p>首先，一个 <code>form</code> 元素包裹着其他的元素。它的 <code>action</code> 设置为 “<code>“example-server.com”</code>”，这是一个假的服务器，表单的数据将被接收。</p><p>在 <code>form</code> 元素之后，其他每个元素也被一个 <code>fieldset</code> 元素所包围，在它下面有一个 <code>legend</code> 标签。</p><p>我们用 <code>fieldset</code> 元素把相关的输入组合在一起，而 <code>legend</code> 标签包含一个注释，传达表单的内容。</p><p><code>name</code>、<code>email</code> 和 <code>textarea</code> 区域的输入都在一个 <code>div</code> 中，其类别为 form-control。所以它们的行为就像一个块状元素，以使 CSS 的样式设计更容易。</p><p>它们也是用 <code>required</code> 属性验证的，所以当这些字段是空的或者用户没有以适当的格式输入数值时，表单就无法提交。</p><p>做完这一切后，我们将得到下面的截图：</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/08/unstyledForm.png" class="kg-image" alt="unstyledForm" width="600" height="400" loading="lazy"></figure><p>这挺难看吧？我们需要应用一些样式！</p><h3 id="css-"><strong>CSS 是这样的：</strong></h3><pre><code class="language-css">body {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100vh;
    font-family: cursive;
  }

 input,
    textarea {
    width: 100%;
    padding: 5px;
    outline: none;
  }

  label {
    line-height: 1.9rem;
  }

  input[type="submit"] {
   transform: translate(2.2%);
   padding: 3px;
   margin-top: 0.6rem;
   font-family: cursive;
   font-weight: bold;
  }

 fieldset {
   padding: 20px 40px;
 }
</code></pre><h4 id="-css-"><strong>这里的 CSS 代码在做什么？</strong></h4><p>我们用 Flexbox 将正文中的所有内容在水平方向上居中，而在垂直方向上则用 100% 的视口高度。我们使用了 <code>cursive</code> 的字体。</p><p>我们给了输入和 <code>textarea</code> 100% 的宽度，这样它们就可以全部穿过。标签的最小行高为 1.9rem（30.4px），所以它们不会离各自的输入端太近。</p><p>我们用 <code>transform</code> 属性特别设计了按钮（输入类型为 <code>button</code>）的样式，把它推到中心，因为它有点偏离中心。我们给它加了一个 3px 的 padding，让它周围有更多的间距。然后我们为它选择了一个 <code>cursive</code> 字体，设置为黑体。</p><p>因为这个按钮离 <code>textarea</code> 太近了，我们设置了 0.6rem 的 margin-top，把它往下推了一点。</p><p>我们给 <code>fieldet</code> 元素在顶部和底部设置了 20px 的 padding，在左边和右边设置了 40px 的 padding，以推开它在它所包裹的 <code>form</code> 元素周围创建的边界。</p><p>在这一切结束后，我们就有了下面这个漂亮的表单：</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/08/styledForm.png" class="kg-image" alt="styledForm" width="600" height="400" loading="lazy"></figure><h2 id="--17"><strong>总结</strong></h2><p>我希望本教程能帮助你了解表单的工作原理。现在你应该掌握了将表单集成到你的网站所需的知识，这样你就可以开始收集数据了。</p><p>谢谢你阅读本文，继续编写代码吧！</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ HTML 按钮链接代码示例——如何使用标签的 HREF 属性制作 HTML 超链接 ]]>
                </title>
                <description>
                    <![CDATA[ 在这篇文章中，我们将探讨三种不同的方法，使 HTML 按钮像链接一样运行。 这些是我们要讨论的方法：  * 为链接设置样式，使它看起来像一个按钮  * 使用表单中的 action 和 formaction 属性  * 使用 JavaScript 的 onclick 事件 但首先，让我们看一下错误的方法。 为什么使用 a 元素的方法不起作用 当下面的代码片段被点击时，会跳转到 freeCodeCamp 网站。   <a href="https://www.freecodecamp.org/">     <button>freeCodeCamp</button>   </a>  然而，这并不是有效的 HTML。 > a 元素可以包裹整个段落、列表、表格等，甚至整个章节，只要其中没有互动内容（如按钮或其他链接）。（来源：网络超文本应用技术工作组 [https://html.spec.whatwg.org/multipage/text-level-semantics.html#the-a-element] ） 这被认为是不好的做法，因为它使用户的意图不明确。 链接应该是为用户导 ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/html-button-link-code-examples-how-to-make-html-hyperlinks-using-the-href-attribute-on-tags/</link>
                <guid isPermaLink="false">63590c17509503074debe9a9</guid>
                
                    <category>
                        <![CDATA[ HTML ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Miya Liu ]]>
                </dc:creator>
                <pubDate>Thu, 27 Oct 2022 10:17:15 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2022/10/6049c377a7946308b76862f0.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>原文：</strong> <a href="https://www.freecodecamp.org/news/html-button-link-code-examples-how-to-make-html-hyperlinks-using-the-href-attribute-on-tags/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">HTML Button Link Code Examples – How to Make HTML Hyperlinks Using the HREF Attribute on Tags</a>
      </p><p>在这篇文章中，我们将探讨三种不同的方法，使 HTML 按钮像链接一样运行。</p><p>这些是我们要讨论的方法：</p><ul><li>为链接设置样式，使它看起来像一个按钮</li><li>使用表单中的 action 和 formaction 属性</li><li>使用 JavaScript 的 onclick 事件</li></ul><p>但首先，让我们看一下错误的方法。</p><h2 id="-a-">为什么使用 a 元素的方法不起作用</h2><p>当下面的代码片段被点击时，会跳转到 freeCodeCamp 网站。</p><pre><code class="language-html">  &lt;a href="https://www.freecodecamp.org/"&gt;
    &lt;button&gt;freeCodeCamp&lt;/button&gt;
  &lt;/a&gt; </code></pre><p>然而，这并不是有效的 HTML。</p><blockquote>a 元素可以包裹整个段落、列表、表格等，甚至整个章节，只要其中没有互动内容（如按钮或其他链接）。（来源：<a href="https://html.spec.whatwg.org/multipage/text-level-semantics.html#the-a-element">网络超文本应用技术工作组</a>）</blockquote><p>这被认为是不好的做法，因为它使用户的意图不明确。</p><p>链接应该是为用户导航到网页的另一部分或外部网站，而按钮应该是执行一个特定的动作，比如提交一个表单。</p><p>当你把一个嵌套在另一个里面时，就会让人搞不清楚你想执行什么动作。这就是为什么最好不要将一个按钮嵌套在一个锚标签内。</p><h2 id="-css-">如何用 CSS 将一个链接设置成按钮的样子</h2><p>这第一种方法根本没有使用按钮。我们可以用 CSS 设置锚点标签的样式，使其看起来像一个按钮。</p><p>这是锚点标签的默认 HTML 样式。</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/03/blue-anchor-tag.png" class="kg-image" alt="blue-anchor-tag" width="600" height="400" loading="lazy"></figure><p>我们可以给锚点标签添加一个类，然后使用该类选择器来为该元素设置样式。</p><pre><code class="language-html">  &lt;a class="fcc-btn" href="https://www.freecodecamp.org/"&gt;freeCodeCamp&lt;/a&gt;  
</code></pre><p>如果你想让这个链接打开一个新的页面，你可以像这样添加 <code>target="_blank"</code> 属性。</p><pre><code class="language-html">  &lt;a target="_blank" class="fcc-btn" href="https://www.freecodecamp.org/"&gt;freeCodeCamp&lt;/a&gt;  
</code></pre><p>然后，我们可以添加一个背景色，改变字体颜色，像这样:</p><pre><code class="language-css">.fcc-btn {
  background-color: #199319;
  color: white;
}</code></pre><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/03/background-and-white-text.png" class="kg-image" alt="background-and-white-text" width="600" height="400" loading="lazy"></figure><p>下一步是在文本周围添加一些填充：</p><pre><code class="language-css">.fcc-btn {
  background-color: #199319;
  color: white;
  padding: 15px 25px;
}</code></pre><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/03/adding-padding-1.png" class="kg-image" alt="adding-padding-1" width="600" height="400" loading="lazy"></figure><p>最后，我们可以使用 <code>text-decoration</code> 属性从文本中删除下划线：</p><pre><code class="language-css">.fcc-btn {
  background-color: #199319;
  color: white;
  padding: 15px 25px;
  text-decoration: none;
}</code></pre><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/03/removing-underline.png" class="kg-image" alt="removing-underline" width="600" height="400" loading="lazy"></figure><p>现在，我们有了一个看起来像按钮的锚标签。</p><p>我们还可以根据链接的状态改变背景颜色，使这个“按钮”更具互动性。</p><pre><code class="language-css">.fcc-btn:hover {
  background-color: #223094;
}</code></pre><p>我们可以进行更复杂的设计，但这只是向你展示像按钮一样的链接的基本样式。</p><p>你也可以选择使用像 <a href="https://getbootstrap.com/">Bootstrap</a> 这样的 CSS 库。</p><pre><code class="language-html">  &lt;a class="btn btn-primary" href="https://www.freecodecamp.org/"&gt;freeCodeCamp&lt;/a&gt;  
</code></pre><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/03/bootstrap-styles.png" class="kg-image" alt="bootstrap-styles" width="600" height="400" loading="lazy"></figure><p>如果你的项目已经包括 Bootstrap，那么你可以使用内置的按钮样式。但我不会为了给一个链接样式而导入 Bootstrap。</p><h3 id="-">这种做法有什么问题？</h3><p>对于将链接样式化为按钮是否是好的做法，存在着一些争论。有些人认为，链接应该总是看起来像链接，而按钮应该看起来像按钮。</p><p>在 <a href="https://resilientwebdesign.com/">Resilient Web Design</a> 一书中，Jeremy Keith 指出</p><blockquote>一种材料不应该被用来替代另一种材料，否则最终的结果是欺骗性的。</blockquote><p>我为什么要费力地提出这个辩论呢？</p><p>我的目的不是要让你在辩论中选择一方而不是另一方，我只是想让你知道这个正在进行的讨论。</p><h2 id="-action-formaction-">如何使用 action 和 formaction 属性在表单中制作一个按钮</h2><h3 id="-action-">如何使用 action 属性</h3><p>另一种方法是将按钮嵌套在表单中并使用 <code>action</code> 属性。</p><p>输入的例子：</p><pre><code class="language-html">  &lt;form action="https://www.freecodecamp.org/"&gt;
    &lt;input type="submit" value="freeCodeCamp"&gt;
  &lt;/form&gt;</code></pre><p>按钮的例子：</p><pre><code class="language-html">  &lt;form action="https://www.freecodecamp.org/"&gt;
    &lt;button type="submit"&gt;freeCodeCamp&lt;/button&gt;
  &lt;/form&gt;</code></pre><p>这将是默认的按钮样式。</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/03/default-button-style.png" class="kg-image" alt="default-button-style" width="600" height="400" loading="lazy"></figure><p>我们可以使用与前面相同的样式，但我们必须添加 <code>cursor</code> 为 <code>pointer</code>，并将边框设置为 none，像这样：</p><pre><code class="language-css">.fcc-btn {
  background-color: #199319;
  color: white;
  padding: 15px 25px;
  text-decoration: none;
  cursor: pointer;
  border: none;
}
</code></pre><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/03/removing-underline-1.png" class="kg-image" alt="removing-underline-1" width="600" height="400" loading="lazy"></figure><h3 id="-formaction-"><strong>如何使用 <code>formaction</code> 属性</strong></h3><p>与前面的方法类似，我们可以创建一个表单并使用 <code>formaction</code> 属性。</p><p>输入的例子：</p><pre><code class="language-html">  &lt;form&gt;
    &lt;input type="submit" formaction="https://www.freecodecamp.org/" value="freeCodeCamp"&gt;
  &lt;/form&gt;</code></pre><p>按钮的例子：</p><pre><code class="language-html">  &lt;form&gt;
    &lt;button type="submit" formaction="https://www.freecodecamp.org/"&gt;freeCodeCamp&lt;/button&gt;
  &lt;/form&gt;</code></pre><p>你只能对 <code>type="image"</code> 或 <code>type="submit"</code> 的输入和按钮使用 <code>formaction</code> 属性。</p><h3 id="--1">这在语义上是否正确？</h3><p>虽然这似乎是一个可行的解决方案，但有一个问题，即这在语义上是否正确。</p><p>我们正在使用表单标签，但这并不像一个真正的表单那样运行。表单的目的是为了收集和提交用户数据。</p><p>但我们使用的是提交按钮，将用户导航到另一个页面。</p><p>当涉及到语义时，这不是一个使用表单标签的好方法。</p><h3 id="-action-formaction--1">使用 action 和 formaction 属性的副作用</h3><p>当你点击按钮的时候，URL 会发生一些有趣的事情。URL 现在在它的末尾有一个问号。</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/03/question-mark-at-end.png" class="kg-image" alt="question-mark-at-end" width="600" height="400" loading="lazy"></figure><p>这种变化的原因是表单使用的是 <code>GET</code> 方法。你可以改用 <code>POST</code> 方法，但可能在某些情况下这也是不理想的。</p><pre><code class="language-html">  &lt;form method="POST" action="https://www.freecodecamp.org/"&gt;
    &lt;button type="submit"&gt;freeCodeCamp&lt;/button&gt;
  &lt;/form&gt;</code></pre><p>虽然这种方法是有效的 HTML，但它确实带来了这种意想不到的副作用。</p><h2 id="-javascript-onclick-">如何使用 JavaScript 的 onclick 事件来制作一个按钮</h2><p>在前面的方法中，我们已经看了 HTML 和 CSS 的解决方案。但我们也可以用 JavaScript 来达到同样的效果。</p><p>输入的例子：</p><pre><code class="language-html"> &lt;form&gt;
    &lt;input type="button" onclick="window.location.href='https://www.freecodecamp.org/';" value="freeCodeCamp" /&gt;
 &lt;/form&gt;</code></pre><p>按钮的例子：</p><pre><code class="language-html">&lt;button onclick="window.location.href='https://www.freecodecamp.org/';"&gt;freeCodeCamp&lt;/button&gt;  
</code></pre><p><code>location.href</code> 代表一个特定的 URL 的位置。在这个例子中，<code>Window.location.href</code> 将返回 <a href="https://www.freecodecamp.org/">https://www.freecodecamp.org/</a>。</p><h3 id="--2">这种方法的缺点</h3><p>虽然这个方案确实有效，但也有一些潜在的问题需要考虑。</p><p>如果用户已经决定在他们的浏览器中禁用 JavaScript，那么显然这个解决方案将无法运行。不幸的是，这可能会导致用户体验不佳。</p><h2 id="--3"><strong>总结</strong></h2><p>这篇文章的目的是向你展示三种不同的方法，你可以使按钮像链接一样运行。</p><p>第一种方法是设计一个看起来像按钮的链接。我们还研究了改变链接的外观使其看起来像另一个元素是否是个好主意的问题。</p><p>第二种方法是使用表单和 <code>formaction</code> 属性。但我们也了解到，这种方法对 URL 有一些副作用，在语义上也不正确。</p><p>第三种方法是使用 JavaScript 的 <code>onclick</code> 事件和 <code>Window.location.href</code>。但我们也了解到，如果用户决定在他们的浏览器中禁用 JavaScript，这种方法可能会失效。</p><p>作为一个开发者，在为你的项目采纳一个特定的方法之前，看看它的优点和缺点真的很重要。</p><p>我希望你喜欢这篇文章，并在其中学到一些东西。</p><p>编码愉快！</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ HTML Div——什么是 Div 标签以及如何用 CSS 为其设置样式 ]]>
                </title>
                <description>
                    <![CDATA[ HTML 分割标签，简称 “div”，是一个特殊的元素，可以让你在网页上把类似的内容集合起来。你可以把它作为关联类似内容的通用容器来使用。 div 标签是使用最多的标签之一，尽管引入了语义元素（这些元素让你使用几个标签作为一个容器），但这个标签仍然被广泛使用。 在本教程中，我将向你展示你可以用 div 标签做的各种事情，你如何在同一个 HTML 文件中使用多个 div 而不混淆它们，以及如何设置其样式。 什么时候使用 div 标签 div 标签的用途很多——你可以用它在一个网页上做几件事。你大部分时间是在网页布局和 CSS 中使用它，但它是超级灵活的。 总的来说，你几乎总是要用它来设计它所包含的任何东西的样式，或者用 JavaScript 来操作这些东西。 在网页布局中使用 div 你将主要使用 div 标签把类似的内容组合在一起，这样你就可以轻松地对其设置样式。一个很好的例子是使用 div  将网页的不同部分组合在一起。你可以把一个页面的标题、导航、章节和页脚放在一个单独的 div 标签中，这样它们就可以一起被设置样式了。 在本教程的后面，我将带你了解如何用多个 div  ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/html-div-what-is-a-div-tag-and-how-to-style-it-with-css/</link>
                <guid isPermaLink="false">635e57c773e419079177b7ed</guid>
                
                    <category>
                        <![CDATA[ HTML ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Miya Liu ]]>
                </dc:creator>
                <pubDate>Tue, 25 Oct 2022 10:19:00 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2022/10/divTag.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>原文：</strong> <a href="https://www.freecodecamp.org/news/html-div-what-is-a-div-tag-and-how-to-style-it-with-css/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">HTML Div – What is a Div Tag and How to Style it with CSS</a>
      </p><p>HTML 分割标签，简称 “div”，是一个特殊的元素，可以让你在网页上把类似的内容集合起来。你可以把它作为关联类似内容的通用容器来使用。</p><p><code>div</code> 标签是使用最多的标签之一，尽管引入了语义元素（这些元素让你使用几个标签作为一个容器），但这个标签仍然被广泛使用。</p><p>在本教程中，我将向你展示你可以用 <code>div</code> 标签做的各种事情，你如何在同一个 HTML 文件中使用多个 <code>div</code> 而不混淆它们，以及如何设置其样式。</p><h2 id="-div-"><strong>什么时候使用 <code>div</code> 标签</strong></h2><p><code>div</code> 标签的用途很多——你可以用它在一个网页上做几件事。你大部分时间是在网页布局和 CSS 中使用它，但它是超级灵活的。</p><p>总的来说，你几乎总是要用它来设计它所包含的任何东西的样式，或者用 JavaScript 来操作这些东西。</p><h3 id="-div">在网页布局中使用 div</h3><p>你将主要使用 <code>div</code> 标签把类似的内容组合在一起，这样你就可以轻松地对其设置样式。一个很好的例子是使用 <code>div</code> 将网页的不同部分组合在一起。你可以把一个页面的标题、导航、章节和页脚放在一个单独的 <code>div</code> 标签中，这样它们就可以一起被设置样式了。</p><p>在本教程的后面，我将带你了解如何用多个 <code>div</code> 标签制作网页布局而不至于混淆。</p><p>除非你对其进行样式设计，否则 <code>div</code> 本身对内容的呈现没有直接影响。</p><h3 id="-css-div"><strong>在 CSS 中使用 <code>div</code></strong></h3><p>使用 <code>div</code> 标签，你可以做出各种形状，画出任何东西，因为设置它的样式很容易。</p><ul><li>如何用 <code>div</code> 标签制作一个正方形</li></ul><p>要用 <code>div</code> 标签制作一个正方形，你首先需要定义一个空的 <code>div</code> 标签，并在 HTML 中为其附加一个 <code>class</code> 属性。在 CSS 中，选择带有类属性的 <code>div</code>，然后为它设置一个相等的高度和宽度。</p><pre><code class="language-html">&lt;div class="square"&gt;&lt;/div&gt;
</code></pre><pre><code class="language-css"> body {
      display: flex;
      align-items: center;
      justify-content: center;
      margin: 0 auto;
      height: 100vh;
      background-color: #f1f1f1;
    }
.square {
      background-color: #2ecc71;
      width: 200px;
      height: 200px;
    }
</code></pre><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/09/square.png" class="kg-image" alt="square" width="600" height="400" loading="lazy"></figure><ul><li>如何用 <code>div</code> 标签制作一个圆</li></ul><p>你可以通过在 HTML 中编码一个空的 <code>div</code>，在 CSS 中为它设置一个相等的高度和宽度，然后设置一个 50% 的 <code>border-radius</code>，来用 <code>div</code> 标签制作一个圆。</p><pre><code class="language-html">&lt;div class="circle"&gt;&lt;/div&gt;
</code></pre><pre><code class="language-css">  body {
      display: flex;
      align-items: center;
      justify-content: center;
      margin: 0 auto;
      height: 100vh;
      background-color: #f1f1f1;
    }

    .circle {
      background-color: #2ecc71;
      width: 200px;
      height: 200px;
      border-radius: 50%;
    }
</code></pre><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/09/circle.png" class="kg-image" alt="circle" width="600" height="400" loading="lazy"></figure><ul><li>如何用 CSS 制作尼日利亚国旗</li></ul><p>用 <code>div</code> 标签制作尼日利亚国旗并不难。国旗是一个长方形，颜色为绿色、白色和绿色。</p><p>要制作它，需要定义 3 个 <code>div</code> 标签并附加不同的类，然后在 CSS 中对其进行适当的样式设置。</p><pre><code class="language-html">&lt;div class="naija-flag"&gt;
    &lt;div class="first-green"&gt;&lt;/div&gt;
    &lt;div class="white"&gt;&lt;/div&gt;
    &lt;div class="second-green"&gt;&lt;/div&gt;
&lt;/div&gt;
</code></pre><pre><code class="language-css">.naija-flag {
  display: flex;
}
.first-green {
  height: 100px;
  width: 60px;
  background-color: green;
}
.white {
  height: 100px;
  width: 60px;
  background-color: white;
}
.second-green {
  height: 100px;
  width: 60px;
  background-color: green;
}
</code></pre><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/09/naija-flag.png" class="kg-image" alt="naija-flag" width="600" height="400" loading="lazy"></figure><h2 id="-div--1">如何为 div 标签设置样式</h2><p>正如我们在上面讨论的那样，设置 <code>div</code> 标签的样式非常容易。这也是许多开发者用它来分组类似内容的原因之一。</p><p><code>div</code> 标签几乎可以毫无问题地接受所有的 CSS 属性。现在让我们看几个例子。</p><h3 id="-div--2">如何用 div 应用字体属性</h3><p>你可以在用 <code>div</code> 标签分组的内容上应用 CSS 属性，如：<code>font-size</code>、<code>font-family</code>、<code>font-weight</code> 和 <code>font-style</code>。</p><pre><code class="language-html">&lt;div class="font-properties"&gt;
      &lt;p&gt;
        Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptate quo
        ullam modi alias assumenda, itaque libero? Quas quidem sint illo.
      &lt;/p&gt;
      &lt;p&gt;
        Lorem ipsum dolor sit, amet consectetur adipisicing elit. Necessitatibus
        ipsam eaque rem dicta, quos quas ipsum.
      &lt;/p&gt;
&lt;/div&gt;
</code></pre><pre><code class="language-css">body {
      max-width: 900px;
      display: flex;
      align-items: center;
      justify-content: center;
      margin: 0 auto;
      height: 100vh;
      background-color: #f1f1f1;
    }

.font-properties {
      font-family: cursive, sans-serif;
      font-size: 1.3rem;
      font-weight: bolder;
      font-style: italic;
    }
</code></pre><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/09/font.png" class="kg-image" alt="font" width="600" height="400" loading="lazy"></figure><h3 id="-div--3">如何用 Div 标签应用颜色</h3><p>你可以在用 <code>div</code> 标签分组的内容上应用 CSS <code>color</code> 和 <code>background-color</code>属性。</p><pre><code class="language-html">&lt;div class="color-properties"&gt;
  &lt;p&gt;
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptate quo
    ullam modi alias assumenda, itaque libero? Quas quidem sint illo.
  &lt;/p&gt;
  &lt;p&gt;
    Lorem ipsum dolor sit, amet consectetur adipisicing elit. Necessitatibus
    ipsam eaque rem dicta, quos quas ipsum.
  &lt;/p&gt;
&lt;/div&gt;
</code></pre><pre><code class="language-css">.color-properties {
  color: white;
  background-color: #2ecc71;
}
</code></pre><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/09/color.png" class="kg-image" alt="color" width="600" height="400" loading="lazy"></figure><h3 id="-div--4"><strong>如何用 Div 标签设置文本的样式</strong></h3><p>你可以像这样在一个 <code>div</code> 标签上应用 CSS <code>text-transform</code> 和 <code>text-decoration</code>属性：</p><pre><code class="language-html">&lt;div class="text-properties"&gt;
  &lt;p&gt;
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptate quo
    ullam modi alias assumenda, itaque libero? Quas quidem sint illo.
  &lt;/p&gt;
  &lt;p&gt;
    Lorem ipsum dolor sit, amet consectetur adipisicing elit. Necessitatibus
    ipsam eaque rem dicta, quos quas ipsum.
   &lt;/p&gt;
&lt;/div&gt;
</code></pre><pre><code class="language-css">.text-properties {
    text-transform: uppercase;
    text-decoration: underline;
  }
</code></pre><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/09/text.png" class="kg-image" alt="text" width="600" height="400" loading="lazy"></figure><h3 id="-div--5">如何用 Div 标签创建阴影效果</h3><p>你可以用 <code>div</code> 标签的 <code>box-shadow</code> 属性来创建阴影效果：</p><pre><code class="language-html">&lt;div class="box-shadow"&gt;
      &lt;p&gt;
        Before paying to learn programming, checkout freeCodeCamp.org
        &lt;br /&gt;
        The HTML, CSS, and JavaScript curricula would take you from zero to hero
        in web development.
      &lt;/p&gt;
      &lt;p&gt;
        There is a Python curriculum that will get you a considerable knowledge
        in Python &lt;br /&gt;
        And an upcoming Data Science curriculum.
      &lt;/p&gt;
&lt;/div&gt;
</code></pre><pre><code class="language-css">.box-shadow {
      font-family: cursive, sans-serif;
      background-color: #2ecc71;
      color: white;
      padding: 10px;
      border-radius: 4px;
      box-shadow: 2px 2px 20px 23px #7fecad;
    }
</code></pre><p>上面的 CSS 中发生了什么？</p><p>我能够用 CSS 中的 <code>box-shadow</code> 属性来创建阴影效果。</p><ul><li>第一个值（2px）代表 X 轴上的偏移量（offset-x）</li><li>第二个值（另一个 2px）代表 Y 轴上的偏移量（offset-y）</li><li>接下来的 20px 是模糊半径，也就是说，你希望阴影有多模糊</li><li>23px 的值是扩散半径（你想让阴影扩散到多远）</li><li>最后一个值是阴影的颜色——在本例中是 #7fecad</li></ul><p>输出结果是这样的：</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/09/box-shadow.png" class="kg-image" alt="box-shadow" width="600" height="400" loading="lazy"></figure><h2 id="-div--6">如何使用多个 Div 元素而不混淆</h2><p><code>div</code> 标签通常用于将类似的内容组合在一起。在旧的甚至一些新的网页中，你会发现到处都是 <code>div</code>，尽管为了可访问性和更好的 SEO，推荐使用语义标签。</p><p>由于 <code>div</code> 标签仍然非常普遍，我建议对它们应用 class 和 id 属性，这样你就可以用这些属性来操作单个 div 元素。</p><p>我将通过制作一个基本的网页布局来指导你如何将此付诸实践。</p><p>你要做的第一个部分是标题，包含 logo 和导航条：</p><pre><code class="language-html"> &lt;div class="header"&gt;
      &lt;h2 class="logo"&gt;freeCodeCamp&lt;/h2&gt;

      &lt;ul class="nav"&gt;
        &lt;li&gt;&lt;a href=""&gt;Home&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=""&gt;About&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=""&gt;Serices&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=""&gt;Contact&lt;/a&gt;&lt;/li&gt;
      &lt;/ul&gt;
&lt;/div&gt;
</code></pre><p>在设计导航条的样式之前，我做了一些 CSS 重设，以使元素正确对齐并显示得很好：</p><pre><code class="language-css">* {
   margin: 0;
   padding: 0;
   box-sizing: border-box;
 }

.hero,
.about,
.services,
.contact {
  max-width: 1000px;
  margin: 0 auto;
  margin-bottom: 20px;
}
</code></pre><p>在上面的代码片断中：</p><ul><li>我删除了默认的 <code>margin</code> 和 <code>padding</code></li><li>我为主要部分设置了一个最大宽度，这样它们就不会占用太多空间，以提高用户体验</li><li>我在每个部分的底部设置了一个边距，给它们一些空间</li><li>我在顶部和底部设置了 <code>margin</code> 为 0，在左侧和右侧设置了 <code>auto</code> 以使它们居中</li></ul><p>为了使导航条具有适当的样式，我将对于 class 属性为 <code>header</code> 的容器 <code>div</code> 标签进行设置。我将给它一个 <code>flex</code> 的 <code>display</code>，以及一些其他属性来很好地设置它。我还将处理包裹导航条（<code>ul</code> 元素）的 <code>div</code>，并用 Flexbox 布局它。</p><pre><code class="language-css">.header {
      padding: 0 70px;
      display: flex;
      align-content: center;
      justify-content: space-between;
      margin-top: 20px;
      margin-bottom: 20px;
    }

.nav {
      display: flex;
      align-content: center;
      justify-content: center;
      gap: 60px;
      list-style-type: none;
    }

.nav li a {
      text-decoration: none;
      color: black;
      font-size: 1.2rem;
    }
</code></pre><p>除了页脚之外，其余部分的 HTML 和样式都是通用的：</p><pre><code class="language-html">&lt;div class="hero"&gt;
      &lt;h1&gt;Hero Section&lt;/h1&gt;
&lt;/div&gt;
&lt;div class="about"&gt;
      &lt;h1&gt;About Us&lt;/h1&gt;
&lt;/div&gt;
&lt;div class="services"&gt;
      &lt;h1&gt;Our Services&lt;/h1&gt;
&lt;/div&gt;
&lt;div class="contact"&gt;
      &lt;h1&gt;Contact Us&lt;/h1&gt;
&lt;/div&gt;
&lt;div class="footer"&gt;
      &lt;p&gt;&amp;copy; 2021 All Rights Reserved&lt;/p&gt;
&lt;/div&gt;
</code></pre><pre><code class="language-css">.hero {
      background-color: #eee;
      height: 200px;
    }

.hero h1 {
      display: flex;
      align-items: center;
      justify-content: center;
      line-height: 6;
    }

.about {
      background-color: #eee;
      height: 200px;
    }

.about h1 {
      display: flex;
      align-items: center;
      justify-content: center;
      line-height: 6;
    }

.services {
      background-color: #eee;
      height: 200px;
    }

.services h1 {
      display: flex;
      align-items: center;
      justify-content: center;
      line-height: 6;
    }

.contact {
      background-color: #eee;
      height: 200px;
    }

.contact h1 {
      display: flex;
      align-items: center;
      justify-content: center;
      line-height: 6;
    }

.footer {
      background-color: #777;
      height: 40px;
    }

.footer p {
      margin: 0 auto;
      line-height: 1.7;
    }
</code></pre><p>我给各个部分的背景颜色为灰色，高度为 200px。我用 Flexbox 将 h1 标签置于其中心位置，并对每个标签应用了 1.5 的行高 <code>line-height</code>。</p><p>最后，我给了页脚一个更深的灰色背景颜色，以使其突出显示，并将内容置于中心位置，行高 <code>line-height</code> 为 1.7。</p><p>最终的布局是这样的：</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/09/layout.gif" class="kg-image" alt="layout" width="600" height="400" loading="lazy"></figure><h2 id="-"><strong>总结</strong></h2><p>Web 开发人员经常使用 HTML <code>div</code> 标签。</p><p>只要记住，你通常应该使用语义 HTML 来代替 <code>div</code> 标签，除非它们（语义标签）都没有真正符合要分组的内容。这是因为语义标签更有利于可访问性和 SEO。</p><p>简而言之，<code>div</code> 标签仍然很有用，而且不会很快消失，所以在必要的时候，请放心使用它。</p><p>谢谢你阅读本文，祝你过得愉快！</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ HTML下拉菜单——如何用 Select 元素添加下拉列表 ]]>
                </title>
                <description>
                    <![CDATA[ 许多网站、应用程序和网页使用下拉菜单来显示信息列表。你可以用它们来创建导航菜单、表格的选项，以及更多。 如果你看其中一些菜单或列表，你可能会想象到创建它们会有多复杂。是的——在某些情况下，它变得有点儿复杂。 下拉菜单是一个选项列表，当用户通过点击菜单或用光标悬停在菜单上与之互动时，该列表会垂直显示。 当用户通过再次点击或将光标从菜单上移开而停止与菜单的交互时，该菜单也会消失。 在这篇文章中，你将学习如何在你的网页上为 select 元素添加一个下拉列表。你还将学习各种可用的选项，以及如何创建一个可悬停的下拉列表/菜单。 如何创建一个 HTML 下拉列表 在 HTML 中，默认情况下，你总是可以用 select 标签和 option 标签一起创建一个下拉列表。这主要是在表单中用于从许多选项的列表中选择一个值。 选择标签有两个主要属性：name 和 id 属性。 // 语法 <select name="" id="">   <option value="">...</option>   // ... </select> 当表单中的选择被提交时，你使用 name 属性来识别 ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/html-drop-down-menu-how-to-add-a-drop-down-list-with-the-select-element/</link>
                <guid isPermaLink="false">63554882509503074debe45b</guid>
                
                    <category>
                        <![CDATA[ HTML ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Chengjun.L ]]>
                </dc:creator>
                <pubDate>Tue, 18 Oct 2022 13:19:00 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2022/10/jackson-sophat-wUbNvDTsOIc-unsplash.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>原文：</strong> <a href="https://www.freecodecamp.org/news/html-drop-down-menu-how-to-add-a-drop-down-list-with-the-select-element/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">HTML Drop-down Menu – How to Add a Drop-Down List with the Select Element</a>
      </p><p>许多网站、应用程序和网页使用下拉菜单来显示信息列表。你可以用它们来创建导航菜单、表格的选项，以及更多。</p><p>如果你看其中一些菜单或列表，你可能会想象到创建它们会有多复杂。是的——在某些情况下，它变得有点儿复杂。</p><p>下拉菜单是一个选项列表，当用户通过点击菜单或用光标悬停在菜单上与之互动时，该列表会垂直显示。</p><p>当用户通过再次点击或将光标从菜单上移开而停止与菜单的交互时，该菜单也会消失。</p><p>在这篇文章中，你将学习如何在你的网页上为 <code>select</code> 元素添加一个下拉列表。你还将学习各种可用的选项，以及如何创建一个可悬停的下拉列表/菜单。</p><h2 id="-html-">如何创建一个 HTML 下拉列表</h2><p>在 HTML 中，默认情况下，你总是可以用 <code>select</code> 标签和 <code>option</code> 标签一起创建一个下拉列表。这主要是在表单中用于从许多选项的列表中选择一个值。</p><p>选择标签有两个主要属性：<code>name</code> 和 <code>id</code> 属性。</p><pre><code class="language-html">// 语法
&lt;select name="" id=""&gt;
  &lt;option value=""&gt;...&lt;/option&gt;
  // ...
&lt;/select&gt;
</code></pre><p>当表单中的选择被提交时，你使用 <code>name</code> 属性来识别下拉。你可以通过把 <code>id</code> 属性和 <code>label</code> 的 <code>for</code> 属性值设置为一样的，来把它们连接起来 。</p><pre><code class="language-html">// 语法
&lt;label for="languages"&gt;List of Languages:&lt;/label&gt;
&lt;select name="" id="languages"&gt;
  &lt;option value=""&gt;...&lt;/option&gt;
  // ...
&lt;/select&gt;
</code></pre><p><code>select</code> 标签也有一些可选的布尔属性，如 <code>disabled</code>（禁用选择字段）、<code>required</code>（使该字段在表单中为必须的），以及更多。</p><pre><code class="language-html">&lt;select name="" id="languages" required&gt;
  // ...
&lt;/select&gt;

// 或者

&lt;select name="" id="languages" disabled&gt;
  // ...
&lt;/select&gt;
</code></pre><p>在 <code>select</code> 标签中，你可以在单个 <code>option</code> 标签中添加许多选项。<code>option</code> 标签有一个 <code>value</code> 的属性，指定了一个选项被选中时从表单中提交的值。</p><pre><code class="language-html">&lt;select name="language" id="language"&gt;
  &lt;option value="javascript"&gt;JavaScript&lt;/option&gt;
  &lt;option value="python"&gt;Python&lt;/option&gt;
  &lt;option value="c++"&gt;C++&lt;/option&gt;
  &lt;option value="java"&gt;Java&lt;/option&gt;
&lt;/select&gt;
</code></pre><p>还有其他布尔属性，如 <code>disabled</code>（禁用菜单中的选项）和 <code>selected</code>（你用它来设置一个特定的选项作为页面加载时的默认选定选项，而不是第一个选项）。</p><pre><code class="language-html">&lt;select name="language" id="language"&gt;
  &lt;option value="javascript" disabled&gt;JavaScript&lt;/option&gt;
  &lt;option value="python"&gt;Python&lt;/option&gt;
  &lt;option value="c++"&gt;C++&lt;/option&gt;
  &lt;option value="java" selected&gt;Java&lt;/option&gt;
&lt;/select&gt;
</code></pre><p>在上面的代码中，第一个选项的属性是 <code>disabled</code>，意味着你将不能选择这个选项。第四个选项的属性是 <code>selected</code>，这意味着不是默认将 JavaScript 作为选择值，而是选择 Java。</p><figure class="kg-card kg-embed-card"><iframe id="cp_embed_YzaNgmw" src="https://codepen.io/olawanlejoel/embed/preview/YzaNgmw?default-tabs=html%2Cresult&amp;height=300&amp;host=https%3A%2F%2Fcodepen.io&amp;slug-hash=YzaNgmw" title="Dropdown List" scrolling="no" frameborder="0" height="300" allowtransparency="true" class="cp_embed_iframe" style="width: 100%; overflow: hidden;" loading="lazy"></iframe></figure><h2 id="-">如何创建一个可悬停的下拉菜单</h2><p>当你滚动浏览或访问许多先进的和现代的网页时，你会注意到它们有下拉菜单。</p><p>这些菜单用于导航，帮助把类似的链接放在一起。大多数时候，当你把鼠标悬停在父菜单上时，就会出现下拉列表。</p><figure class="kg-card kg-image-card"><img src="https://paper-attachments.dropbox.com/s_B4C6D2ADDF91C398F7D0077C06A79A5494062ED47759B85768844AD11A4B757E_1664053790313_image.png" class="kg-image" alt="s_B4C6D2ADDF91C398F7D0077C06A79A5494062ED47759B85768844AD11A4B757E_1664053790313_image" width="600" height="400" loading="lazy"></figure><p>你可以通过各种方式创建这些类型的菜单，因为没有直接的语法来建立一个菜单。</p><p>你可以使用 CSS 样式来创建，当用户在菜单上悬停时显示和隐藏下拉列表。一个非常好的方法是创建一个容纳菜单和下拉列表的 <code>div</code>。</p><pre><code class="language-html">&lt;div class="dropdown"&gt;
  &lt;button&gt;Profile&lt;/button&gt;
  &lt;div class="dropdown-options"&gt;
    &lt;a href="#"&gt;Dashboard&lt;/a&gt;
    &lt;a href="#"&gt;Setting&lt;/a&gt;
    &lt;a href="#"&gt;Logout&lt;/a&gt;
  &lt;/div&gt;
&lt;/div&gt;
</code></pre><p>这个 <code>div</code> 作为一个容器，你可以把它设置为 <code>position</code> 为 <code>relative</code>，和 <code>display</code> 为 <code>inline-block</code>，这样下拉选项就会出现在菜单下面。</p><pre><code class="language-css">.dropdown {
  display: inline-block;
  position: relative;
}
</code></pre><p>你可以按照自己的想法设计按钮和下拉选项。但控制悬停效果的主要样式，默认情况下，将 <code>dropdown-options</code> 设置为不显示。那么，当鼠标悬停在菜单上时，<code>display</code> 不会被设置为 <code>block</code>，所以选项是可见的。你还将 <code>position</code> 设置为 <code>absolute</code>，所以选项出现在菜单下面，并将 <code>overflow</code> 设置为 <code>auto</code>，以便在小屏幕上进行滚动。</p><pre><code class="language-css">.dropdown-options {
  display: none;
  position: absolute;
  overflow: auto;
}

.dropdown:hover .dropdown-options {
  display: block;
}
</code></pre><p>在下面的演示中，我们添加了更多的样式，使下拉菜单更有吸引力更美观。</p><figure class="kg-card kg-embed-card"><iframe id="cp_embed_ZExZGdK" src="https://codepen.io/olawanlejoel/embed/preview/ZExZGdK?default-tabs=css%2Cresult&amp;height=300&amp;host=https%3A%2F%2Fcodepen.io&amp;slug-hash=ZExZGdK" title="Hoverable dropdown menu" scrolling="no" frameborder="0" height="300" allowtransparency="true" class="cp_embed_iframe" style="width: 100%; overflow: hidden;" loading="lazy"></iframe></figure><h2 id="--1"><strong>总结</strong></h2><p>在这篇文章中，你已经学会了如何用 <code>select</code> 标签创建一个下拉列表。你还学习了如何用 CSS 处理悬停效果来创建可悬停的下拉菜单。</p><p>你可以在<a href="https://chinese.freecodecamp.org/news/html-select-tag-how-to-make-a-dropdown-menu-or-combo-list/">《HTML select 标签——如何制作下拉菜单或组合列表》</a>文章中了解更多关于 <code>select</code> 标签的信息。</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ HTML 字体大小——如何用 HTML 标签改变文本大小 ]]>
                </title>
                <description>
                    <![CDATA[ 当你用 HTML 标签添加文本到 HTML 文件中时，有时你需要调整文本在浏览器中的显示方式。 在这篇文章中，你将学习如何用 HTML 标签改变文本大小。 在继续之前，你必须知道我们只有一种方法可以做到这一点：通过 CSS 的 font-size 属性，我们可以通过内联、内部或外部样式设计来使用 font-size  属性。 在过去，我们可以在 HTML 标签中调整文本大小而不使用 CSS。但那是在 HTML5 之前。我们使用标签添加文本，它可以接受一个 size 属性，如下图所示： <font size="5">       Hello World  </font>   这个 size 属性的取值范围是 1-7，其中文本大小从 1 增加到 7。但就像我说的，这个方法已经过时了，大多数人甚至不知道它的存在。 如果你急着想知道如何改变你的文本大小，那就来看看吧。 // 使用内联 CSS <h1 ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/how-to-change-text-size-in-html/</link>
                <guid isPermaLink="false">6348dae731b59b077bbb1e24</guid>
                
                    <category>
                        <![CDATA[ HTML ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Miya Liu ]]>
                </dc:creator>
                <pubDate>Tue, 11 Oct 2022 03:16:00 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2022/10/root-font-size-article-image.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>原文：</strong> <a href="https://www.freecodecamp.org/news/how-to-change-text-size-in-html/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">HTML Font Size – How to Change Text Size with an HTML Tag</a>
      </p><p>当你用 HTML 标签添加文本到 HTML 文件中时，有时你需要调整文本在浏览器中的显示方式。</p><p>在这篇文章中，你将学习如何用 HTML 标签改变文本大小。</p><p>在继续之前，你必须知道我们只有一种方法可以做到这一点：通过 CSS 的 <code>font-size</code> 属性，我们可以通过内联、内部或外部样式设计来使用 <code>font-size</code> 属性。</p><p>在过去，我们可以在 HTML 标签中调整文本大小而不使用 CSS。但那是在 HTML5 之前。我们使用标签添加文本，它可以接受一个 <code>size</code> 属性，如下图所示：</p><pre><code class="language-html">&lt;font size="5"&gt;  
    Hello World 
&lt;/font&gt;  
</code></pre><p>这个 <code>size</code> 属性的取值范围是 1-7，其中文本大小从 1 增加到 7。但就像我说的，这个方法已经过时了，大多数人甚至不知道它的存在。</p><p>如果你急着想知道如何改变你的文本大小，那就来看看吧。</p><pre><code class="language-html">// 使用内联 CSS
&lt;h1 style="font-size: value;"&gt; Hello World! &lt;/h1&gt;

// 使用内部/外部 CSS
selector {
    font-size: value;
}
</code></pre><p>假设你并不着急。让我们深入了解一些。</p><h2 id="-css-">如何用内联 CSS 改变文本大小</h2><p>内联 CSS 允许你将样式应用于特定的 HTML 元素。这意味着我们直接将 CSS 放入一个 HTML 标签。我们使用 <code>style</code> 属性，它存放我们所有的样式。</p><pre><code class="language-html">&lt;h1 style="..."&gt;Hello World!&lt;/h1&gt;
</code></pre><p>我们使用 <code>font-size</code> 属性和相应的值，通过内联 CSS 来改变文本大小。这个值可以使用任何你喜欢的 CSS 单位，如 em、px、rem 等等。</p><pre><code class="language-html">&lt;h1 style="font-size:4em; "&gt; Hello World! &lt;/h1&gt;
&lt;p style="font-size:14px; "&gt; Any text whose font we want to change &lt;/p&gt;
</code></pre><p>完美的语法应该是：</p><pre><code class="language-html">&lt;TEXT-TAG style="font-size:value;"&gt; ... &lt;/TEXT-TAG&gt;
</code></pre><h2 id="-css--1">如何用内部或外部 CSS 改变文字大小</h2><p>你用来改变内部和外部 CSS 样式的文字大小的方法是相似的，因为你使用了一个选择器，语法如下：</p><pre><code class="language-css">selector {
    font-size: value;
}
</code></pre><p>选择器可以是我们的 HTML 标签，也可以是一个类或一个 ID，比如：</p><pre><code class="language-html">// HTML
&lt;p&gt; Any text whose font we want to change &lt;/p&gt;

// CSS
p {
    font-size: 14px;
}
</code></pre><p>或者我们可以使用一个类：</p><pre><code class="language-html">// HTML
&lt;p class="my-paragraph" &gt; Any text whose font we want to change &lt;/p&gt;

// CSS
.my-paragraph {
    font-size: 14px;
}
</code></pre><h2 id="-"><strong>小结</strong></h2><p>在这篇文章中，你学到了如何使用 CSS 来改变 HTML 元素的字体/文本大小。你还看到了在引入 HTML5 之前，开发者是如何做到这一点的。</p><p>另外，请记住，使用内部或外部样式来设计你的 HTML 元素总是更好的，因为与内联样式相比，它具有很大的灵活性。</p><p>例如，你可以为所有的 <code>p</code> 标签使用一个 CSS 类，而不是为所有的 <code>p</code> 标签元素添加内联样式。</p><p>使用内联样式并不被认为是最佳做法，因为它导致了大量的重复——你不能在其他地方重复使用这些样式。要了解更多，你可以阅读我的文章<a href="https://chinese.freecodecamp.org/news/inline-style-in-html/">《如何在 HTML 中使用 CSS 内联样式》</a>。</p><p>我希望这个教程能帮助你理解如何改变 HTML 文本大小，让你能够创建更好的网页。</p><p>祝你编码愉快！</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ HTML 背景图片——如何将墙纸图片添加到你的网站上 ]]>
                </title>
                <description>
                    <![CDATA[ 背景图片可以帮助美化网站，使其对用户更具吸引力。 在这篇文章中，你将了解到：  * 如何使用 CSS 的 background-image 属性为你的网站添加背景图像  * 其他用于图像的 CSS 背景属性 如何在你的网站上添加墙纸图像 在开发一个网站时，使用图像作为网站的背景图像与在 HTML 中使用 img 元素插入图像是不同的。 要使用图像作为网站的背景，你要使用 CSS。 下面是一个例子： <!DOCTYPE html> <html lang="en"> <head>     <link rel="stylesheet" href="style.css">     <title>Background Image</title> </head> <body>     <h1>Background image</h1> </body> ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/html-background-image-how-to-add-wallpaper-images-to-your-website/</link>
                <guid isPermaLink="false">633aadfd96409407bcba351f</guid>
                
                    <category>
                        <![CDATA[ HTML ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Chengjun.L ]]>
                </dc:creator>
                <pubDate>Mon, 26 Sep 2022 09:19:00 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2022/10/jonatan-pie-3l3RwQdHRHg-unsplash.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>原文：</strong> <a href="https://www.freecodecamp.org/news/html-background-image-how-to-add-wallpaper-images-to-your-website/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">HTML Background Image – How to Add Wallpaper Images to Your Website</a>
      </p><p>背景图片可以帮助美化网站，使其对用户更具吸引力。</p><p>在这篇文章中，你将了解到：</p><ul><li>如何使用 CSS 的 <code>background-image</code> 属性为你的网站添加背景图像</li><li>其他用于图像的 CSS 背景属性</li></ul><h2 id="-">如何在你的网站上添加墙纸图像</h2><p>在开发一个网站时，使用图像作为网站的背景图像与在 HTML 中使用 <code>img</code> 元素插入图像是不同的。</p><p>要使用图像作为网站的背景，你要使用 CSS。</p><p>下面是一个例子：</p><pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
    &lt;link rel="stylesheet" href="style.css"&gt;
    &lt;title&gt;Background Image&lt;/title&gt;
&lt;/head&gt;

&lt;body&gt;
    &lt;h1&gt;Background image&lt;/h1&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre><pre><code class="language-css">h1{
    text-align: center;
}</code></pre><p>我们上面有两个代码块——HTML 代码在网页上显示 “Background image” 的文字，而 CSS 代码则将文字放在页面的中心。</p><p>要在网站上添加一个墙纸图像——一个覆盖整个页面的图像——你必须为 <code>body</code> 元素编写一些 CSS 规则，方法如下：</p><pre><code class="language-css">body{
    background-image: url('bg-image.jpg');
}</code></pre><p>在上面的代码中，我们使用 <code>background-image</code> 属性在网页正文中添加一个图片。图片的路径/位置被作为参数传递给 <code>url()</code> 函数：<code>url('bg-image.jpg')</code>。</p><p>下面是网页现在的样子：</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/news/content/images/2022/09/full-bg-image.PNG" class="kg-image" alt="full-bg-image" width="600" height="400" loading="lazy"></figure><h2 id="--1">如果背景图像比浏览器窗口小怎么办</h2><p>在图像小于浏览器的情况下，图像会重复几遍，以铺满剩余的空间。</p><p>这种重复并不是使每张图片都看起来很好。下面是上一节中使用的图片的缩小版在浏览器中的样子。</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/news/content/images/2022/09/repeat.PNG" class="kg-image" alt="repeat" width="600" height="400" loading="lazy"></figure><p>图像已经被分割成四个不均匀的部分。如果你不需要这种效果，你可以用 <code>background-repeat</code> 属性来修复它。</p><p>下面是如何解决图像重复的问题：</p><pre><code class="language-css">body{
    background-image: url('bg-image-small.jpg');
    background-repeat: no-repeat;
}
</code></pre><p>在上面的代码中，我们给 <code>background-repeat</code> 属性分配了一个 <code>no-repeat</code> 值。</p><p>下面是网页现在的样子：</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/news/content/images/2022/09/small-image.PNG" class="kg-image" alt="small-image" width="600" height="400" loading="lazy"></figure><p>图片不再在整个页面上重复，但我们有一个新的问题——图片不再覆盖整个页面。</p><p>为了解决这个问题，我们使用 <code>background-size</code> 和 <code>background-attachment</code> 属性。</p><pre><code class="language-css">body{
    background-image: url('bg-image-small.jpg');
    background-repeat: no-repeat;
    background-size: cover;
    background-attachment: fixed;
}</code></pre><p>将 <code>background-size</code> 属性的值设置为 <code>cover</code>，使图像覆盖整个元素（在我们的例子中是 <code>body</code>/整个页面）。</p><p>通过值为 <code>fixed</code> 的 <code>background-attachment</code> 属性，图像的位置是固定的。这样，即使你滚动页面，它也会保持在同一位置。</p><p>这就是现在的图片：</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/news/content/images/2022/09/cover-image.PNG" class="kg-image" alt="cover-image" width="600" height="400" loading="lazy"></figure><p>将一张小图片拉伸到覆盖整个页面的缺点是，图片在被拉伸的过程中会降低质量，变得模糊不清。所以，在使用小图片作为网站的背景图片之前，你应该考虑这个问题。</p><h2 id="--2"><strong>小结</strong></h2><p>在这篇文章中，我们谈到了在网站上添加墙纸图片的问题。</p><p>你可以使用 CSS 的 <code>background-image</code> 属性为你的网站添加一个背景图片。</p><p>我们还学习了如何使用其他 CSS 背景属性，如 <code>background-repeat</code>、<code>background-size</code> 和 <code>background-attachment</code>。</p><p>祝你编程愉快！</p> ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
