
先说句实在话很多人学HTML资料找了一大堆真到自己动手写网页还是习惯从别人的页面里复制一堆标签过来改。HTML标签这事说难也不难说简单也真不简单——它就像盖房子搭骨架骨架歪了后面再怎么刷CSS、贴JavaScript都别扭。这篇文章我把日常开发里出场率最高的HTML常见标签系统过一遍从文档结构到表单控件结合我这些年实际踩过的坑和项目经验让你看完就能自己徒手写出一张完整的网页。不管你是刚入门的前端新人、想自己搭个人主页的非技术人员还是要维护老项目的半路出家选手这篇都能当一份随时翻查的速查手册。1. 先把骨架搭对文档结构与头部标签1.1 一个HTML页面最基本的骨架长什么样很多人一开始就纠结各种花哨标签反而忽略了一个页面最基础的开头四五行。其实一个标准HTML5文档的骨架非常固定我每次新开工都会先敲出这一套!DOCTYPE html html langzh-cn head meta charsetutf-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 title页面标题/title /head body !-- 页面可见内容都写在body里 -- /body /html这里每个部分都别小看。!DOCTYPE html不是标签是文档类型声明它的作用是告诉浏览器“我是HTML5文档请按标准模式解析”。如果不写老浏览器会进入“怪异模式”盒模型、边距这些全部和你预期的对不上明明代码没问题页面就是歪的。你搜HTML源码时经常看到!doctype htmlhtml langzh-cn开头就是因为几乎每个正经页面的第一行都是它。html langzh-cn里的lang属性很多人直接忽略但它影响两件事一是屏幕阅读器读网页时会按这个语言发音二是浏览器翻译插件会据此判断是否需要翻译。中文页面统一写成zh-cn最省事繁体页面用zh-hk或zh-tw。head里的meta charsetutf-8更是重中之重这个标签负责告诉浏览器“网页文字用UTF-8编码”一旦缺失或写错中文直接变成乱码。我在维护老项目时不止一次遇到文件用了GBK编码、页面声明却写成UTF-8的情况结果整个页面全是锟斤拷排查半天才找到根源——不是代码逻辑错是编码声明和实际不一致。1.2 head里除了meta charset还有哪些值得写的meta标签head区域是页面的“后台办公室”里面内容用户看不见但浏览器、搜索引擎、社交平台分享机器人都在看。除了必写的字符集日常最常用的还有这几个meta namedescription content页面描述给搜索引擎看的页面摘要往往出现在搜索结果标题下方。meta nameviewport contentwidthdevice-width, initial-scale1.0移动端适配的关键不写这行手机打开页面就是缩小版桌面视图字小得看不清。title页面标题/title浏览器标签页上显示的文字也是搜索引擎结果里的大标题。分享网页到微信或聊天软件时卡片标题也取自这里所以千万别空着。另外还有两个经常被混淆的东西link用来引入外部CSS文件script用来引入JavaScript。很多人把script放在head里结果页面加载慢了半拍其实现代实践更推荐把不依赖DOM的脚本放在body底部或者给script加defer属性。至于那些网上整段复制出来的!doctype htmlhtml langzh-cnheadmeta charsetutf-8...我建议你自己动手敲一遍因为复制十次不如手写一次记得牢。1.3 写HTML到底该用什么编辑器Ubuntu上怎么选编辑器这块很多人纠结半天其实写HTML最朴素的工具就是纯文本编辑器。Windows自带记事本能写但没有任何语法高亮标签嵌套错了只能靠肉眼找效率太低。我推荐VS Code跨平台免费Windows、Linux、macOS都能装Ubuntu下一条命令搞定sudo snap install code --classic安装完再装一个Live Server插件右键HTML文件就能起本地预览服务改代码浏览器自动刷新学习体验会舒服很多。如果你只是偶尔改两行Ubuntu自带的gedit、或者在终端里用nano、vim也完全够用没必要为了写个demo折腾IDE。顺带回答一个热门搜索“html格式转换wps表格”。WPS表格打开HTML文件或另存为HTML是没有问题的因为HTML本质就是纯文本加标记。但如果你是想把网页里的表格数据塞进WPS表格最靠谱的办法不是“转换”而是复制页面里的数据在WPS表格里选择性粘贴为“文本”或者用WPS自带的“从网页导入数据”功能。不要指望有一个按钮能把整张网页变成完美表格那是两套完全不同的数据处理思维。2. 文字排版正文标签全家桶2.1 标题、段落、换行和分隔线的基本用法页面内容九成以上是文字所以文本类标签是使用频率最高的。标题从h1到h6一共六级视觉上从大到小。这里有个老生常谈的规矩一个页面通常只保留一个h1它是整页内容的主标题搜索引擎理解页面主题很大程度上就看它。下面再按层级用h2、h3划分章节。有些人图省事标题样式全靠CSS撑、标签乱用比如把正文文字放大冒充标题这会让SEO和读屏软件完全摸不清你的文档结构。p是段落标签浏览器会在段落前后自动留出间距。br是强制换行hr是水平分隔线。我自己早期写过很糟糕的代码用五六个br把元素往下推用一堆空p撑间距后来被同事骂了一顿才醒悟——br本身没有“留白”的语义它只是换行要间距应该用CSS的margin和padding。用br硬撑出来的页面一改字号或换屏宽就全线崩盘维护成本极高。2.2 加粗、斜体、下划线strong和b到底选谁想让一段字加粗你有两个选择strong和b。视觉上看效果一模一样但语义差别很大。strong表示“这个内容很重要”是语义上的强调b只是“视觉上加粗”没有附加含义。对屏幕阅读器和搜索引擎来说strong的分量明显更重所以正经正文里请用strongb留着做纯粹的样式钩子。斜体同理em是语义强调i只是斜体外观很多图标字体也习惯用i当容器因为对它来说斜不斜根本不重要。在HTML5里u下划线标签也被重新定义了它现在更多用来表示“文本拼写错误”或“专有名词标注”并不是简单的“加下划线”。我自己现在的习惯是一切纯视觉需求都交给CSSHTML标签只负责“这个内容是什么”。比如“注意这里不能踩坑”我会用strong包起来如果只是设计稿上要求某几个字是红色、加粗我绝不会去翻什么标签直接写个span再加CSS类名。想改样式却到处找标签是新手最爱犯的路线错误。2.3 span、div还有那个“已经退役”的font标签div和span是HTML里最中性的两个容器也是被误解最深的两个标签。div是块级元素默认占满整行像一个“集装箱”适合划分页面大区块span是行内元素不会把内容换行像一片“包装纸”适合给段落里的某几个字挂样式。很多人问“span标签是干什么用的”一句话回答它是行内容器用来圈出一小块内容好让CSS或JavaScript精准操作它。至于font标签老教程里经常出现font colorred size3这种写法用来直接控制文字颜色和字号。HTML5早已把它标记为“不推荐使用”因为它把“长什么样”和“是什么内容”混在一起改样式得满文件找font标签太痛苦。现在的原则很清晰HTML管结构和语义CSS管视觉样式。font虽然浏览器还能兼容显示但新代码里不要再用同理还有center和marquee。你如果看到老项目里有一堆font和marquee滚动字幕别奇怪那是那个年代的技术债能重构就重构不能重构至少知道它是历史遗留而不是学习方向。3. 链接与图片让页面不再是白纸黑字3.1 a标签怎么打开新窗口以及一个容易忽略的安全问题a是网页里最核心的交互标签没有它互联网就不成网了。最基础写法是a hrefhttps://example.com title鼠标悬停提示访问示例站/ahref是跳转目标title是悬停提示。想让链接在浏览器新标签中打开用target_blanka hrefhttps://example.com target_blank relnoopener noreferrer新窗口打开/a这里有个很多人不知道的坑如果只写target_blank而不加relnoopener noreferrer新打开的页面可以通过window.opener拿到并操作你原页面的DOM。恶意网页可以趁你原页面还在后台时悄悄把它改成钓鱼页面等你切回去一看满屏假登录框。这不是危言耸听属于真实存在的安全风险。所以凡是外部链接relnoopener noreferrer必须带上这是我在公司code review里反复强调的点。还有人问火狐浏览器点网页里的链接怎么总是“跳转新标签”这其实分两层如果链接写了target_blank火狐默认是新建标签页打开不是新窗口如果没写target你按住Ctrl键点击或按鼠标中键也会强制在新标签打开这是浏览器自己的操作习惯跟HTML没有关系。想在火狐里让链接直接开新窗口需要去浏览器设置里调整标签页行为那是浏览器配置问题不是写网页的人能控制的。3.2 img标签和图片点击弹出图层的实现思路图片标签img是自闭合标签没有结束标签这一点和a明显不同。基础写法img srcimages/logo.png alt公司Logo width200 height100src填图片路径alt在图片加载失败或屏幕阅读器朗读时显示是必填项至少写个alt别留空。width和height写成HTML属性可以让图片在加载时预先占位避免页面文字跳来跳去但真正的响应式缩放建议交给CSS。图片路径是新手第一大坑相对路径、绝对路径、根相对路径三种写法容易混src./images/a.png和srcimages/a.png在绝大多数情况下等价但src/images/a.png表示从站点根目录出发完全不同。图片显示红叉时按F12打开开发者工具看Network面板里的加载状态比瞎猜快得多。“img标签点击跳出图层”是另一个高频搜索词。很多人以为这是img的属性其实它和img本身关系不大实现思路是图片绑定一个click事件JavaScript弹出一个半透明遮罩层遮罩层里放大展示大图再点击遮罩关闭。这种效果业内叫lightbox有成熟的开源方案。也就是说HTML标签只负责“放图片”和“被点击”弹出图层的逻辑在CSS和JS那边。搞清楚这层分工你就不会再指着img标签找有没有“弹层属性”了。3.3 音频、视频和iframe嵌入audio和video是HTML5新增的多媒体标签用法非常直观video controls width640 source srcmovie.mp4 typevideo/mp4 /video audio controls source srcsong.mp3 typeaudio/mpeg /audiocontrols属性决定是否显示播放控件autoplay是自动播放但现代浏览器普遍拦截带声音的自动播放实在要自动播只能静音播或等用户点击后再放声音——这是浏览器针对用户体验的统一策略不是你的代码写错了。iframe用来在页面里嵌入另一个网页或视频但要注意很多网站设置了X-Frame-Options头禁止被嵌入你辛辛苦苦写好iframe一预览发现是空的往往不是代码问题而是对方不允许。3.4 浏览器“标签页”和HTML里的“标签”不是一回事搜索“标签”这个词的人有一半可能搜错了对象。浏览器顶部那个可以切换网页的“标签页”英文叫Tab本质是浏览器管理多页面的功能HTML里的标签英文叫Tag指的是div、img这种代码标记。两者中文同名但完全是两个世界的东西。有人搜“Chrome标签页分组怎么隐藏”那是在问浏览器操作在Chrome里右键某个标签页选择“添加到新组”再右键组名可以重命名、换颜色点组名左侧的箭头就能折叠或隐藏这个组。这些操作跟写网页没有任何关系纯粹是浏览器的用户操作。另外也有人在搜“tabs标签页”或“vue3修改tabs标签页样式”那是前端组件开发里的“标签页切换组件”比如Element Plus的Tabs组件。这类组件本质还是HTML加CSS加JS想改样式要去看组件的API和CSS变量已经不是“常见HTML标签”的范畴了。一句话总结先分清你搜的“标签”到底指哪个领域的东西——硬件领域的“三星内存条标签怎么看”、电路设计里的“嘉立创网络标签”、工控里的“变量标签”和网页开发也完全无关。中文词汇的多义性在这个词上体现得淋漓尽致。4. 表格与列表结构化的基本功4.1 表格的基本结构和它不该再承担的任务table标签是HTML里传承最久的结构标签之一但它的职责在CSS成熟后发生了翻天覆地的变化。二十年前做网页布局几乎全是table套table一层层嵌套出三栏版式。今天再用表格做布局就是自己给自己挖坑——表格天生不适合响应式改一处结构可能牵动整个页面维护难度极高。现在表格只有一个正当用途展示结构化数据比如购物订单、课程表、统计报表。基础表格由table、tr、td、th构成。tr是行td是普通单元格th是表头单元格浏览器默认给th加粗居中。更完整的结构会把表头包在thead里、正文包在tbody里方便浏览器分块渲染。早期写法喜欢在table上写border1画边框现在统一用CSS的border-collapse: collapse来控制更灵活也更好维护。4.2 colspan标签到底是什么合并单元格的正确姿势有人单独搜索“colspan标签是什么”说明表格合并单元格是他绕不过去的坎。colspan不是独立标签而是写在td或th上的属性表示这个单元格横跨多少列。比如table tr th科目/th th上午/th th下午/th /tr tr td rowspan2语文/td td8:00/td td13:00/td /tr tr td9:00/td td14:00/td /tr /tablerowspan2表示这个“语文”单元格纵向跨两行。这个表格一共三列但第二行里面只写了三个td第一个带rowspan后面两个普通这样就对应上了。合并单元格最经典的坑是合并之后忘了减少同行的其他单元格数量浏览器会自动补位表格看起来就像被什么东西挤了一下整体错位。我排查这类问题就一招数每一行的td总数横向有没有colspan都按实际占据的列数算哪一行加起来不是总列数哪里就漏写了或写多了。4.3 无序列表、有序列表和自定义列表列表类标签在页面里无处不在导航菜单、新闻列表、商品特性、步骤说明都是用列表搭的。ul是无序列表默认前面带圆点适合没有先后顺序的内容ol是有序列表默认带数字适合步骤、排名li是列表项必须挂在ul或ol下面才合法。还有一个出场率不那么高但很实用的dl自定义列表里面是dt标题加dd描述结构天然适合做术语表、功能说明这种“名词解释”的成对内容。嵌套列表时有个新手常犯的错误想在一个大列表下面再套一个子列表结果把子ul直接放在了父ul的下级浏览器虽然也能显示但结构不合法。正确的姿势是把子列表写在父列表项li的内部就像文件夹里套文件夹子文件必须放进父文件夹里而不是和父文件夹平级。5. 表单标签收集用户输入的全家桶5.1 form和input是表单的核心type类型怎么选表单是HTML里所有交互数据的入口注册、登录、搜索、下单背后都有一堆表单标签在工作。整个表单外围是formform action/login methodpost !-- 各种输入控件 -- /formaction是提交地址method是提交方式。get会把这些字段拼到URL后面适合搜索场景post把数据放在请求体里适合提交敏感数据。登录注册表单必须用post否则账号密码会直接出现在URL地址栏里截图分享出去等于公开泄漏。input是使用频率最高的表单标签靠type属性区分功能text普通文本、password密码框、email邮箱、number数字、checkbox复选框、radio单选框、file文件上传、hidden隐藏字段。移动端浏览器对typeemail和typenumber会调出对应的专用键盘这个细节很多人不做用户体验直接差一截。这里有个极常见的误区placeholder是输入框的提示占位文字不是默认值。新手经常写了placeholder请输入姓名就以为输入框里已经有内容了结果表单提交后发现字段是空的——因为placeholder根本不会被当作value提交。真要给默认值用value属性。5.2 label、name和id三角关系必须理清表单里最容易被忽视但极其重要的是label标签。它的作用是把一段说明文字和一个输入控件关联起来点击文字就能让输入框获得焦点。写法是label的for属性指向输入框的idlabel forusername用户名/label input typetext idusername nameusername placeholder请输入用户名这个关联对鼠标用户、触屏用户和读屏软件都至关重要。没有label的表单点击范围只有输入框本身用户点偏了就白点体验很差。name和id也经常有人混为一谈id是页面内的唯一标识给JavaScript和label用的name才是表单提交到服务器时用的“字段名”。没有name的控件根本不会提交数据。我在排查“后端收不到参数”的问题时第一件事永远是检查每个输入控件有没有写name十次里有八次是这个原因。有些场景要用到富文本或自定义渲染比如有人问“pyqt5显示html”那属于桌面应用内嵌HTML渲染PyQt5的QTextBrowser可以直接setHtml渲染带样式的HTML但渲染能力有限复杂表单、最新CSS特性经常支持不好。这是另一个技术栈的话题核心要记住的是HTML标签在任何环境里都遵循同一套规范差别只在于“渲染环境能支持到什么程度”。5.3 select、textarea和button的三个经典坑select下拉框的基础写法select namecity option valuebeijing北京/option option valueshanghai selected上海/option /select提交给后端的是value属性里的值不是option里显示的文字。selected表示默认选中很多人写了selected却忘了写value结果提交了一堆显示文字后端解析起来很痛苦。textarea是多行文本域它有个隐蔽的坑开始标签和结束标签之间如果存在换行或空格这些空白会被当成初始内容显示出来。我遇到过同事写的textarea打开就多一行空白折腾半天才发现是标签格式太“工整”了。正确写法是textarea nameintro/textarea内容贴在一起需要默认文字就直接在中间写字。button的坑更典型放在form里的button默认type是submit也就是你一按它就提交表单。很多新手想做一个“普通按钮”写了button点我/button就完事结果每次点击页面都刷新。解决方法很简单——明确写typebutton。5.4 表单提交后页面刷新了怎么办原生form提交的默认行为就是把页面跳转到action指定的地址这是正常的。如果你不想刷新页面就得借助JavaScript拦截监听form的submit事件调用e.preventDefault()阻止默认提交再用fetch或axios把数据异步发到后端。很多新手以为“页面刷新”是代码出错了纠结很久其实那只是浏览器执行了表单默认行为。另外a标签也可以伪装成按钮提交表单但那是JavaScript套路的活不推荐在基础阶段学。6. 语义化标签让代码长得像文档结构6.1 header、nav、main、article、section、aside、footer早年间写页面整个结构基本是“div工厂”div classheader.../div div classnav.../div div classcontent.../div所有区块都叫div光靠class区分别人接手你的代码得在几十个div里猜谁是干嘛的。HTML5引入了真正的语义化标签相当于给页面文档加了“目录”body header站点头部/header nav导航/nav main article文章主体/article aside侧边栏/aside /main footer页脚/footer /bodyheader是页头nav是导航区main是页面主体一个页面只应有一个article是一篇独立成块的文章section是文档里的章节分组aside是侧边栏或补充内容footer是页脚。这套结构的好处很实际搜索引擎能更快识别哪里是导航、哪里是正文屏幕阅读器可以跳过导航直接朗读正文开发者也一眼能看出页面骨架。我接手的项目里凡是代码review清晰的项目语义化标签的使用都相当规范。article和section的选择标准我自己的经验是这块内容从页面里拿出去单独放到别处还能独立成立就用article它只是当前页面里的一个章节片段就用section。很多人问“语义化对SEO到底有没有用”我的回答是有用但别神话。结构清晰是搜索引擎理解页面的基础就像简历排版清楚比堆满关键词更让人事愿意看但光靠语义化也不能让一个空页面排到第一。另外现在前端框架里经常提到“tabs标签页”组件这类组件的可访问性标准做法会用到roletablist、roletab这些ARIA角色。如果你用Vue 3配Element Plus做Tabs组件想改样式通常是通过CSS变量或:deep选择器覆盖内部节点这已经是组件化和CSS范畴的实践和HTML常见标签已经隔了一层。但底层逻辑还是同样的HTML结构只是被封装了。6.2 语义化之后div和span还能不能用了当然能用而且必须用。语义化标签解决的是“页面框架定性”的问题但页面里还有很多内容既不是导航也不是文章就是个用来挂CSS样式的壳。这时候div就是最诚实的选择你非要给它套个article反而语义错误。原则是先想这块内容是什么再决定标签想不出来是什么含义那就div。我见过有人为了“语义化”把纯装饰性的图标包在article里那比用div还糟糕因为它给读屏软件传达了错误信息。span的定位同样如此它是行内中性容器用来圈住一小段文字或一个图标方便CSS精确控制。div和span不是被语义化标签“淘汰”了而是回归了它们本来的角色——中性的、无语义的布局容器。语义化标签管“这是页头”“这是导航”div和span管“这里我需要一个钩子”。两者分工明确缺一不可。7. 常见问题排查与避坑实录7.1 高频问题速查表写HTML不像写程序会直接报错崩溃它的“报错”方式是页面显示不符合预期。下面这张表是我这些年处理过的高频问题按“症状→原因→解法”整理基本覆盖了新手阶段能踩到的大多数坑症状主要原因解法中文乱码缺少meta charset或文件编码不一致统一使用UTF-8编码head里写meta charsetutf-8图片不显示路径写错、文件名大小写不对、防盗链F12看Network里的加载状态从相对路径开始排查点链接没反应href写错、写了href#或漏了href检查href真实地址锚点跳转写完整#id表单提交后页面刷新原生表单的默认提交行为用JavaScript的preventDefault()拦截或用fetch异步提交新窗口打开后原页面被篡改target_blank缺relnoopener外部链接统一加relnoopener noreferrertextarea多出空白行标签内部有换行和空格textarea的起始标签和内容紧贴表格整体错位colspan/rowspan与td数量不匹配逐行数td实际占据列数保证总和等于总列数按钮一按就提交button默认type是submit普通按钮显式写typebutton光看表还不够我建议你把每一条都亲手复现一遍再修复。比如表格错位刻意写错一次再看浏览器怎么显示你对合并单元格的理解会深刻很多。纸上得来终觉浅HTML尤其如此。7.2 输入热词里那些“周边问题”一次讲清楚搜索“HTML标签”的很多人其实是带着具体问题来的我把几个常见周边问题也顺手整理一下html转md用pandoc最省心Ubuntu下装一下命令是pandoc input.html -t markdown -o output.md。Python里也可以用html2text库适合批量处理。打包多个html如果是一组静态页面直接压缩成zip传到服务器就能用如果想合并成一个单文件需要把公共CSS和JS内联到页面里但页面间跳转依赖href天生就是多文件结构别为了“单文件”把架构搞复杂。data:text/html浏览器地址栏直接输入data:text/html,h1你好/h1就能预览一段HTML适合随手验证标签效果。但只适合临时测试别用在正经项目里。html一键返回顶部最简单的方法是在页面顶部放一个idtop的元素然后用a href#top回到顶部/a想要平滑滚动效果用window.scrollTo({ top: 0, behavior: smooth })。html邮件邮件客户端普遍不支持JavaScript很多连外部CSS和class选择器都不认所以EDM邮件排版用的是“古老”的table布局加内联样式。如果你要写邮件模板忘掉div加class那套现代做法回到表格嵌套不然主流邮箱里直接破版。百度首页天气这种demo核心并不是HTML标签而是要接天气API获取数据再把数据渲染进div或span里。初学者想练手可以先用假数据把页面搭起来再逐步替换成真实接口这样能把“结构和样式”与“数据和逻辑”分开学。7.3 我踩过几次坑后总结的硬经验写HTML代码时我个人的习惯是“先写结束标签再写内容”。用VS Code的Emmet插件输入div按Tab会自动生成div/div先把闭合结构立起来再往中间填内容这样嵌套再深也不会出现“找不到闭合标签”的惨案。另一个习惯是命名class时用结构语义来命名比如.article-title、.user-card而不是.red-text、.left-box——前者的类名描述“这是什么”后者的类名描述“长什么样”一旦设计稿改版后者会让你改到怀疑人生。标签和属性统一小写HTML虽然大小写不敏感但XHTML和XML是敏感的统一小写能避免迁移时不必要的坑。还有一件事是关于XML的。搜索引擎经常带出“xml格式文件没有标签怎么办”这种问题。XML和HTML长得像但规则严格得多XML里所有标签必须成对闭合、属性必须加引号、空元素也要自闭合没有浏览器那种“帮你容错”的机制。如果你拿到一个XML文件“没有标签”多半是格式化问题用任意的XML格式化工具或编辑器插件跑一遍缩进就能看清结构。理解HTML标签时会越来越顺手因为规则更严格的东西你都会了宽松的自然不在话下。我自己写了十多年页面最大的体会是HTML常见标签真的不用死记把上面这些用熟踏踏实实做一两个完整页面比刷一百道标签选择题管用得多。我最初也对着font、marquee研究过半天后来才明白那些都是该退役的旧东西。现在每次新项目开工我基本都会先把DOCTYPE、meta charset、viewport这三行写好就像出门先穿鞋一样自然。你要是把这篇里的标签都手动敲过一遍再顺手踩过几个坑恭喜你你已经算真正起步了。