本文公众号来源:我没有三颗心脏
作者:我没有三颗心脏
本文已收录至我的GitHub
前言
现在我们来学习一些基础的 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>Java3y</title>
</head>
<body>
<p>欢迎:Java3y</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
选择器价值 10 -
tag
选择器价值 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 来实现。至此,我们已经对它们有了最基础的了解。
- End -
《对线面试官》系列目前已经连载19篇啦!进度是一周更新两篇,欢迎持续关注
-
【对线面试官】Java注解 -
【对线面试官】Java泛型 -
【对线面试官】 Java NIO -
【对线面试官】Java反射 && 动态代理 -
【对线面试官】多线程基础 -
【对线面试官】 CAS -
【对线面试官】synchronized -
【对线面试官】AQS&&ReentrantLock -
【对线面试官】线程池 -
【对线面试官】ThreadLocal -
【对线面试官】CountDownLatch和CyclicBarrier -
【对线面试官】List -
【对线面试官】Map -
【对线面试官】SpringMVC -
【对线面试官】Spring基础 -
【对线面试官】SpringBean生命周期 -
【对线面试官】Redis基础 -
【对线面试官】Redis持久化
发表评论