HTML/ CSS 入门
前言
我们在之前的学习中,对于网络有了一定的了解。现在我们来学习一些基础的 HTML/ CSS 知识。希望阅读完这篇文章能达到编写简单页面的程度。
目录:
- HTML/ CSS 的发明;
- HTML 基础;
- CSS 基础;
- 页面是如何渲染的;
Part 1. HTML/ CSS 的发明
1989 年 3 月,互联网还只属于少数人。
同年,蒂姆·伯纳斯·李(Tim Berners-Lee)提出了一种能让远隔两地的研究者们共享知识的设想。
这一想法的实践促使了万维网的诞生。它基于现有的 TCP/IP 协议构建,包括 4 个部分:
- 一种表示超文本文档的文本格式,即超文本标记语言(HTML);
- 一种用于交换这些文档的简单协议,即 HyperText 传输协议(HTTP);
- 一个客户端可以显示这些文档,第一个 Web 浏览器称为 WorldWideWeb。
- 一个可以访问文档的服务器;
这四部分在 1990 年底完成。虽然此时 Web 页面只能显示单纯的文本内容,浏览器也只能显示呆板的文字信息,不过这已经基本满足了建立 Web 站点的初衷,实现了信息资源共享。
从 HTML 被发明开始,样式就以各种形式存在。不同的浏览器结合它们各自的样式语言为用户提供页面效果的控制。
随着 HTML 的成长,为了满足页面设计者的要求,HTML 添加了很多显示功能。但是随着这些功能的增加,HTML 变的越来越杂乱,而且 HTML 页面也越来越臃肿。于是 CSS 便诞生了。
1995 年 www 网络会议上 CSS 被提出。同年,W3C 组织成立,层叠样式表的开发就此走上正轨。
HTML 负责网页内容,CSS 负责内容的基本样式。
Part 2. HTML 基础
什么是 HTML
HTML 是 Hper Text Markup Language 的简称,即超文本标记语言。它就像我们熟知的 Word 一样,只不过它适用于 Web。
HTML 同 Word 一样提供了标题、段落、列表、表格、图像、粗体、斜体等文本来构建文档。关键区别在于 Word 中的格式文本是可视的,而 HTML 代码纯粹是语义的。
HTML 基础
像任何语言一样,HTML 带有一组规则。这些规则相对简单,就是要界定界限——知道从哪里开始,从哪里结束。
例如,HTML 表示的段落将被写为:
说明:
- 一对尖括号 (
<
/>
)中间的就是 HTML 标签。 - 不同的标签有不同的含义。这里的
p
代表了一个段落的意思; - HTML 标签通常成对出现,开始标签(
opening tag
)<p>
定义了段落的开始,结束标签(closing tag
)</p>
定义了结束; - 开始和结束标签之间唯一的区别就是标签名称前的斜杠
/
; - 当您把开始标签和结束标签以及两者之间所有内容组合在一起时,就获得了一个 HTML 元素;
- 标签(尖括号内的内容都)不会被显示,仅仅用于区分内容的语义并提供一些默认的样式;
在哪里写 HTML?
就像我们熟知的 .txt
文本文件一样, HTML 文档(后缀为 .html
)也可以使用任意文本编辑器打开。
打开您的任一文本编辑器,然后复制并粘贴以下内容:
<p>这是我的第一个网页</p>
将文件另存为 my-first-webpage.html
,然后使用浏览器将其打开,您就会看到:
但实际上,我们一般会选择更加专业的软件:
属性
属性就像绑定到 HTML 元素的额外信息一样。它们写在 HTML 标签内,所以,浏览器也不会显示它们。
例如,href
属性就是用来定义 a
标签跳转目标链接的属性:
<a href="https://www.wmyskxz.com/">点击会跳转到我的主页</a>
有 16 个 HTML 属性可用于任何 HTML 元素,所有这些都是可选的。
我们最常用的就是 class
属性(用于 CSS)。
一些 HTML 元素具有强制属性。例如,插入图片时,必须使用 src
(source)属性来提供图像的位置:
<img src="#" alt="Description of the image">
考虑到 <img>
标签的意义,强制性的要求设置显示图像的路径,是有意义的。
注释
如果你有一些不想显示但是又想提醒代码阅读者的一些事情,通常可以添加注释。
HTML 注释以 <!--
开始,以 -->
结束。如下所示:
<!-- This is an HTML comment -->
<!-- This is a multi-line HTML comment
that spans across more than one line -->
<p>This is a normal piece of text.</p>
您还可以注释掉部分 HTML 代码来进行调试,如下所示:
<!-- Hiding this image for testing
<img src="images/smiley.png" alt="Smiley">
-->
自封闭元素
一些 HTML 元素只有一个开始标签:
<br> <!-- 换行标签 -->
<img src="#" alt="Description"> <!-- 图像标签 -->
<input type="text"> <!-- 文字输入标签 -->
因为它们没有结束标签,因此内部不能包含任何内容。所以自封闭元素通常带有一些属性,以便为它们提供附加信息。
HTML 块和内联
在 HTML 中,您主要会遇到两种类型的 HTML 元素:
块元素用于通过将内容划分为连贯的块来构造页面的主要部分。
<p>这是第一段内容</p>
<p>这是第二段内容</p>
内联元素旨在区分文本的一部分,以赋予其特定的功能或含义。内联元素通常包含一个或几个单词。
<p>如果感兴趣,可以点击<a href="https://www.wmyskxz.com">这里</a>来访问我的主页</p>
开始和结束标签
所有块级元素都有一个开始和结束标签。
所以,自封闭元素都是内联元素,仅仅是因为它们的语法不允许它们包含任何其他 HTML 元素。
HTML 层次结构
HTML 文档就像一棵大的家族树,上面有父母、兄弟姐妹、孩子、祖先和后代等。
这源于 HTML 元素具有相互嵌套的功能。
嵌套
让我们编写一个简单的段落,并通过插入两个内联元素来区分文本各个部分来对其进行增强:
<p>
<strong>培根</strong>曾经说过:<q>合理安排时间,就等于节约时间</q>。
</p>
结果:
其中:
<strong>
对「培根」这一个词语进行了强调;<q>
对「合理安排时间,就等于节约时间」这句话加上了引号;
使用 <strong>
会加粗标签内的内容,这只是浏览器的默认行为。请注意:您必须根据 HTML 元素的含义而非其外观来选择 HTML 元素。
这种情况下:
<p>
是<strong>
和<q>
标签的父元素;<strong>
和<q>
同为<p>
元素的子元素;<strong>
和<q>
是同级元素;
顺序
如何嵌套 HTML 文档取决于打开和关闭标签的位置。
由于 HTML 元素包含打开和关闭标签,以及介于两个标签之间的内容,一个子元素的关闭必须结束于父元素之前。
<!-- This is INVALID code! :-( -->
<p>
This HTML code won't work because I the "strong" tag is opened here <strong>but is only closed after the paragraph.
</p></strong>
上述代码是不合法的,因为 <strong>
标签打开在 <p>
标签之后(因此 <strong>
被认为是 <p>
的子元素),所以 <strong>
必须在 <p>
元素关闭之前关闭。
<!-- This is valid code. :-) -->
<p>
This HTML code will work because I the "strong" tag is opened <strong>and closed</strong> properly.
</p>
深度
由于子元素本身可以包含其他子元素,所以可以在 HTML 文档中编写更深的层次结构。
例如,我们可以编写一段:
<article>
<h1>题图故事:光努力是没有用的</h1>
<p>
漫画家蔡志忠有一个演讲,题目叫做<a href="https://www.yuque.com/book-academy/share/shp7tu">《努力是没有用的》</a>。读完这份演讲稿,我觉得他说的有道理。
</p>
<p>
有些人非常勤奋,别人休息和娱乐的时候,都在工作学习。但是努力了一辈子,人生也没有显著的提升,就像报道里经常说的:<q>某某在平凡的岗位上,勤勤恳恳工作了一辈子</q>。
</p>
<p>
另一方面,很多成功者似乎也没有特别努力,就取得了许多成就,过上了好日子。蔡志忠以自己为例,他从小就喜欢画画,然后一直画,不知不觉就成了大漫画家,名利双收,从没有觉得过得很辛苦。
</p>
</article>
结果:
在这种情况下,该 HTML 文档的家族树看起来会是这样:
<h1>
和三个 <p>
是兄弟姐妹;每个 <p>
的父亲都是 <article>
;每个元素(除开 <article>
)都是 <article>
的后代;
块元素和内联元素嵌套
块元素可以包含块元素或内联元素。
但是,内联元素只能包含其他内联元素。(<a>
标签除外)
<!-- This is INVALID code! :-( -->
<strong>
<p>You can't put a paragraph inside a "strong" tag.
</strong>
但是要记住元素的家族树。这种层次结构在 CSS 中很有用。
HTML 是语义的
HTML 标记的目的是向文档传递含义。所以不必担心网页的外观,应该关心每个标签的含义。
选择合适匹配的元素
根据要编写的内容,可以选择与文本含义相匹配的适当元素。
不要过分考虑语义
大约有 100 个语义 HTML 元素可供选择。遍历该列表并为您的内容选择适当的元素可能会让人不知所措。
但是不要花太多时间担心这一点。基本上能用好上面的标签就足够好了。
一个有效的 HTML 文档
HTML 文档需要特定的结构才能生效。
文档类型
提供的第一个信息就是我们正在编写的 HTML 文档的类型:Doctype。
曾经有很多 HTML 版本共存。如今,HTML 5 已经成为规范。
所以,我们要告诉浏览器这个 HTML 文档是 HTML 5 的版本,只需要在最开始写上:
<!DOCTYPE html>
注意:HTML 是大小写不敏感的。这意味着你只需要单词拼写对就可以了——但仍需要保持规范。
HTML 5 文档类型没有提到数字 “5” 的原因是:W3C 认为以前的文档类型定义太混乱了,借机吧任何 HTML 版本的信息都给简化掉了。
<html>
元素
除了 doctype 外,所有 HTML 文档都必须包装在一个 <html>
元素内:
<!DOCTYPE html>
<html>
<!-- The rest of your HTML code is here -->
</html>
<head>
<head>
标签相当于整个页面(<html>
包裹的内容)的属性。为整个页面提供了附加的额外信息,并且不会显示。
例如,文档的标题就包含在 <head>
标签内:
<!DOCTYPE html>
<html>
<head>
<title>网页标题</title>
</head>
</html>
<body>
<body>
使我们编写所有网页内容的地方。里面的所有内容都会显示在浏览器窗口中。
完整的有效 HTML 文档
综合所有这些要求,我们可以编写一个简单有效的 HTML 文档:
<!DOCTYPE html>
<html>
<head>
<title>我没有三颗心脏</title>
</head>
<body>
<p>欢迎关注公众号:wmyskxz</p>
</body>
</html>
浏览器视角:
Part 3. CSS 基础
为什么存在 CSS?
随着 90 年代网络的普及,将特定设计应用于网站的意图也随之增强。Web 开发人员依靠特定的 HTML 标签来增强网页显示:
<basefont>
为整个 HTML 文档定义了一种字体<font>
为它包含的文本定义字体,颜色和大小<center>
将所有内容水平居中<big>
增加文字大小<strike>
带有删除线的渲染文本
也可以使用几个 HTML 属性:
bgcolor
在元素上定义背景色text
定义文字颜色- 几个
margin
属性可用于在元素的任何一侧添加间隔的空间
但最重要的是,为了创建视觉上对齐(通常是彼此定位)的元素,Web 开发人员通常会使用 <table>
来设计网页,因为它自然地提供了视觉网格:
但这种方法很麻烦,原因如下:
- HTML
<table>
定义是冗长的:它们需要很多样板代码 - 标签在语义上是错误的:
<table>
应该用于多维数据 - 更改布局需要更改标签:如果我们想将左列移动到右侧,则必须修改 HTML 结构
- 容易出现语法错误:行和单元格需要按特定顺序进行排序和嵌套才能有效
- 标签不可读:表格之间相互嵌套
这就是为什么逐渐放弃使用表进行布局的原因,而改用 CSS 的原因。
什么是 CSS?
CSS 是 Cascading Style Sheets 的缩写,即层叠样式表。其目的是为标记语言(如 HTML 或 XML)设置样式。因此,CSS 本身一文不值,除非与 HTML 文档相关联。
CSS 通过设置字体、颜色,定义边距、定位元素、动画交互等等,使 HTML 文档栩栩如生。
CSS 是如何工作的?
CSS 的工作方式是选择一个 HTML 元素(如一个段落),选择一个要更改的属性(如颜色),并应用一个特定的值(如红色):
p {color: red;}
"样式" 一词可能具有欺骗性。CSS 不仅仅可以用于修改文本的颜色、大小、字体等,还可以用来定义高度、宽度、内部和外部的边距、位置等。
我在哪里写 CSS?
CSS 作为标签属性
您可以使用 style
属性直接在 HTML 元素上编写 CSS:
<p style="color: red;">This paragraph will be red.</p>
结果:
<head>
中的 CSS
您也可以在 <head>
中使用 <style>
标签来使用 CSS:
<html>
<head>
<title>Hello World</title>
<style type="text/css">
p{ color: red;}
</style>
</head>
<body>
<p>This paragraph will be red.</p>
</body>
</html>
结果:
CSS 在单独的文件中
您也可以把 CSS 编写为带有 .css
扩展名的单独文件,然后使用 <link>
标签来将其链接到 HTML 中:
p{ color: red;}
<html>
<head>
<title>Hello World</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<p>This paragraph will be red.</p>
</body>
</html>
目录结构:
Desktop
├── style.css
├── my-first-webpage.html
结果:
这种单独使用一个 CSS 文件的方法是优选的。
为什么不直接在 HTML 中设置样式?
因为我们要把内容和其表示形式分开。这样做的好处显而易见。
首先是可阅读性变高了,有哪些元素,以及元素哪些属性一目了然,也利于分别维护和修改。(类似于书的目录和对应内容一样)
另外是你可以提炼一些通用的属性来减少描述:
简而言之:更易维护、更灵活。不过应该怎么描述是相当看经验的。
CSS 基础语法
CSS 的目的是定义 HTML 元素的布局和样式。语法非常简单:
/* A CSS rule */
selector{ property: value;}
您也可以将其看作是:
who{ what: how;}
CSS 选择器
因为我们不想一次为所有 HTML 元素设置样式,所以我们需要能够定位这些 HTML 元素的子集。
CSS 选择器定义了我们希望样式应用到哪些元素。
通用标签选择器
定位通用 HTML 标签很容易:只需使用标签名称即可。
a{ /* Links */ }
p{ /* Paragraphs */ }
ul{ /* Unordered lists */ }
li{ /* List items */ }
HTML 标签的名称和所使用的 CSS 选择器之间存在直接联系。
class
考虑到我们可能不希望所有段落或所有标题的样式都相同,因此需要区分它们。
在所有 HTML 属性中,该 class
属性对于 CSS 来说是最重要的。它允许我们定义一组专门设计的 HTML 元素。只需在要使用的类名前面加一个点 .
:
.date {
color: red;
}
这样,所有具有 class="redColor"
的 HTML 元素都会被设置为红色:
<p class="date">
Saturday Feb 21
</p>
<p>
The event will be on <em class="date">Saturday</em>.
</p>
结果:
IDs
你也可以使用 id
属性来作用于 HTML,只需要在 CSS 选择器前面加上 #
:
#tagline{ color: orange;}
<h1 id="tagline">This heading will be orange.</h1>
id
属性有点类似于 class
属性,但 id
只能作用于唯一一个 HTML 元素,而 class
可以作用于一类。
一些例子
组合选择器
我们重用之前的示例,该实例中,我们希望日期显示为红色:
.date {
color: red;
}
<p class="date">
Saturday Feb 21
</p>
<p>
The event will be on <em class="date">Saturday</em>.
</p>
但如果我们希望 em
元素中的日期改为蓝色应该怎么办?我们可以添加以下 CSS:
em.date {
color: blue;
}
结果:
该 em.date
选择器仅适用于 <em class="date"></em>
的 HTML 元素。它不会影响 .date
或 em
。
层级选择器
选择器中的空格定义祖先/后代关系。假设我们希望标题中的链接为红色:
header a {
color: red;
}
可以读作:"选择 header
标签内所有的 a
元素"。这样可以防止所有其他链接(不在标题中)受到影响。
伪类选择器
HTML 元素可以具有不同的状态。最常见的情况是当您将鼠标悬停在链接上时。当此类事件发生时,CSS 中可能会应用不同的样式。
伪类选择器附加到常规选择器上,并以冒号开头:
:
/* 正常情况下的样式 */
a {
color: blue;
}
/* 鼠标悬停时的样式 */
a:hover {
color: red;
}
CSS 继承
假设我们要更改网页的文本颜色,为每个 HTML 元素指定颜色将很麻烦:
p,
ul,
ol,
li,
h1,
h2,
h3,
h4,
h5,
h6{ color: grey;}
值传递
但其实 color
值是可以从祖先继承的。考虑到我们要更改整个页面,我们可以选择所有 HTML 元素的祖先 body
标签:
body{ color: grey;}
所有子元素和后代元素都将从其共同祖先继承该值。
当然我们也可以使用
html
标签。
继承的属性
只能从祖先那里继承少数 CSS 属性。它们主要是文本属性:
- 文字颜色
- 字体(大小/ 字体 Family/ 样式/ 粗细)
- 行高
一些 HTML 元素不会从其祖先那里继承。例如,链接(
<a>
标签)不继承该color
属性。
CSS 优先级
一个 HTML 元素可以被多个 CSS 规则作为目标。让我们以一个简单的段落为例:
<p class="message" id="introduction">
欢迎关注公众号:wmyskxz
</p>
我们有三种方式使用 CSS 来对其设置样式:
/* 标签名 */
p{ color: blue;}
/* 类名 */
.message{ color: green;}
/* id */
#introduction{ color: red;}
由于浏览器只能选择一种颜色应用于该段落,因此必须决定哪种 CSS 规则优先于其他规则。这就是 CSS 优先级。
在我们的示例中,该段落将为红色,因为#id
选择器比其他选择器具有更高优先级。
CSS 规则的顺序
如果您的 CSS 中有类似的选择器,则最后定义的选择器将具有优先权。
p{ color: green;}
p{ color: red;}
/* Paragraphs will be red */
快速判断的方法
判断 CSS 优先级的一种快速方法是给选择器的打分:
#id
选择器价值 100.class
选择器价值 10tag
选择器价值 1
无论 CSS 出现的顺序如何, “得分”最高的选择器都将优先。
#introduction{ color: red;}
.message{ color: green;}
p{ color: blue;}
<p class="message" id="introduction">
欢迎关注公众号:wmyskxz
</p>
结果这一段将是红色的。因为 #introduction{ color: red;}
ID 选择器具有更高的优先级。
如何避免冲突
在编写CSS时,很容易编写有冲突的规则,比如多次应用同一属性。
为了避免这种情况:
- 仅使用类:使用
.introduction
代替#introduction
,即使该元素仅在您的网页中出现一次 - 避免在单个 HTML 元素上应用多个类:不要编写
<p class="big red important">
,而是<p class="title">
在语义上更具描述性; - 不要使用像这样的内联样式
<div style="background: blue;">
CSS 常用属性一览表
body {
width:100px;/*宽度*/
min-width:1000px;/*最小宽度*/
height :100px;/*高度*/
line-height:100px;/*行高*/
font-family:SimSun,"Microsoft YaHei";/*字体*/
font-size :16px;/*字体大小*/
font-style :italic;/*字体风格*/
font:16px/26px "微软雅黑";/*字号/行高 字体*/
color:#ccc;/*字体颜色*/
border-width:10px;/*四边边框粗细*/
border-style:solid;/*四边边框的风格*/
border-color:red;/*四边边框的颜色*/
border:10px solid red;/*border-width,border-style,border-color的简写*/
border-top-width:10px;/*上边框的粗细*/
border-top-style:dashed;/*上边框的风格*/
border-top-color:red;/*上边框的颜色*/
border-top:10px solid red;/*上面三个简写*/
border-radius:2px;/*边框圆角*/
text-align:center;/*left,center,right,justify 水平方向居中*/
letter-spacing:10px;/*字间距*/
word-spacing:10px;/*单词之间的间距*/
text-indent:10px;/*首行缩进*/
margin-top:10px;/*上外边距*/
margin:10px;/*四边外边距*/
padding-top:10px;/*上内边距*/
padding :10px;/*可以设置一,二,三,四种值.内边距*/
float:left;/*right 左浮动,右浮动*/
clear :both;/*清除浮动,,清除左浮动或者右浮动*/
position:relative;/*相对定位*/
position:absolute;/*绝对定位*/
position:fixed;/*固定定位*/
z-index:1;/*设置层叠元素的上下位置*/
background-color:#ddd;/*背景颜色*/
background-image:url("");/*背景图片*/
overflow:hidden;/*溢出部分隐藏*/
visibility:hidden;/*隐藏,占位置*/
display:block;/*设为块状元素 块级元素自带的属性*/
display:inline;/*设为行内元素*/
display:inline-block;/*非块状元素的块状盒子*/
display:none;/*隐藏,不占位置*/
opacity:0.5;/*透明度 兼容ie9以上的浏览器*/
filter:alpha(opacity=50)/*设置透明度 兼容i6~ie8*/
}
Part 4. 页面是如何渲染的
浏览器具有运行在操作系统之上的"操作系统"的"美称"。这意味着这是一个相当复杂的过程。
对于浏览器如果感兴趣的话,可以参考之前的文章。这里简单回顾一下。
首先,渲染进程内部包含主线程、工作线程、合成线程和光栅线程。
请先想象一个这样的场景:您站在一副简单绘画的面前,如何通过打电话来让您的朋友知道这幅画究竟长什么样子呢?
浏览器实际上要知道绘制些什么元素,每个元素属性如何是要分成三步的:1)通过 HTML 绘制元素树(俗称 DOM 树);2)通过 CSS 文件绘制样式树(俗称 CSSOM 树);3)综合两颗树绘制渲染树(俗称 Render Tree);
现在浏览器知道文档的结构、每个元素的样式、页面的几何形状和绘制顺序,它是如何绘制页面的?把这些信息转换为屏幕上的像素,我们称为光栅化。
处理这种情况的一种简单的方法是,先在光栅化视窗内的画面,如果用户滚动页面,则移动光栅框,并光栅化填充缺少的部分。这就是 Chrome 首次发布时处理光栅化的方式。
但是,现代浏览器会运行一个更复杂的过程,我们称为合成。
合成是一种将页面的各个部分分层,分别光栅化,并在称为合成线程的单独线程中合成为页面的技术。如果发生滚动,由于图层已经光栅化,因此它所要做的只是合成一个新帧。动画也可以以相同的方式(移动图层和合成新帧)实现。
后记
如今我们纷繁复杂的网页几乎都靠 HTML 和 CSS 来实现。至此,我们已经对它们有了最基础的了解。
这一个系列的文章是准备尝试跟着后端学习路线图的脚步跟着大家一起学习进阶。后续还会继续更新,请持续关注。
Hi,这里是我没有三颗心脏,在公众号 wmyskxz 分享一个自由技术人的成长和思考,2021,与您在 Be Better 的路上共同成长!