CSS(Cascading Style Sheets)层叠样式表
CSS和HTML的关系
HTML用于描述数据.CSS用于描述样式,CSS是为人准备的,为的是更直观, 更好看.CSS是不是只能用于给HTML提供样式呢? 答案:不是, 会更上一层.HTML属于XML的一种特例,CSS可用于描述XML.
当然今天主要讨论的是HTML下的CSS.
样式的定义
抛开基础不谈(基础都不谈, 谈啥, 哈哈), 下面这串代码就是CSS中一个完备的代码块,可直接在HTML中使用
h1,h2,h3 {
margin: 0 0 1px 0;
}
这段最简单的CSS; 可分为两部分:
(1): h1,h2,h3(这一块叫选择器, 这里表示选中HTML文档中的三类标签h1,h2,h3)
(2)
{
margin: 0 0 1px 0;
}
这是一个声明块, 用于规定HTML的样式, 其中的margin: 0 0 1px 0;是一条申明语句, 表示: 想象一个长方形, 从上面开始, 顺时针旋转, 外边距(距离其他元素的距离)依次为 0、0、1px:一个像素点、0
把(1)和(2)总结一下: 当前页面(HTML)的所有的h1、h2、h3标签, 对上、右、左三边的相邻元素0间距.对下边的相邻元素1个像素点的间距
这就是一段完整的CSS.
接下来考虑如何把这段代码生效呢? 如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
// 看这里,把代码CSS放这里就可以了
h1,h2,h3 {
margin: 0 0 1px 0;
}
</style>
</head>
<body>
<h1>H1</h1>
<h2>H2</h2>
<h3>H3</h3>
</body>
</html>
用一个style标签包裹起来放到HTML中, 就大功告成.
样式引入
上面已经让样式生效了, 但其实生效的方式不止一种, 其实有三种, 接下来看一下:
- 内部样式: 把样式写在
<style></style>标签内, 这就是上面例子使用的方式了. - 内联样式: 直接把样式内容写在
HTML标签上, 就上面说的声明语句,也可以直接写在HTML的具体标签上; - 外部样式: 把刚上面的样式写在独立的文件内
.css文件, 在通过style, link标签引入HTML.
具体可参考文章: CSS样式(内联、内部、外部)_内联样式-CSDN博客
选择器
真正在具体开发过程中, 开发者一般是不提倡使用内联样式的, 一般都是外部样式或者内部样式. 而一篇能够实现具体功能的HTML, 它的代码量是很大的, 为了能够精准的控制一篇HTML中具体的每一个元素的样式, 选择器其实是很复杂的, 上面距离其实是最简单的那种. 接下来我们需要详细的聊一聊CSS的选择器, 让样式精准指向具体的HTML元素.
请进入第二小节(看完记得回来):
3.1 [一步步跑完前端学习路线] 前端内容系统化梳理-层叠样式表-CSS-样式的绑定和选择器选择器 当你看过内部样式和 - 掘金 (juejin.cn)
样式生效的优先级
如果你认真的看了选择器一章节, 你一定会发现, 选择器选中的结果绝大部分都是集合(符合某些特征的一类元素), 集合一定会存在交叉的情况, 某一个元素可能会同时属于集合A和集合B, 如果A让该元素的字体大小为13px, B让元素的字体大小为18px, 这时候该听谁的? 这就是CSS的优先级问题. 而且HTML和XML不同, 每一个元素都是带有默认样式的. 基于这些原因, 就需要有一个合理的规范, 规定谁的优先级最高.
怎么做才合理先不讨论, 我们只去学习, 这个合理的规范是什么样的?
在讨论优先级之前, 需要额外再了解一两个概念: 默认值、继承
CSS属性默认值
我们一般会通过申明语句来定制元素的样式, 但是HTML元素即使在我们没有显式定义的情况下, 也会存在默认的样式, 这是因为元素会自带属性默认值, 具体默认值为何, 需要查询相关文档: color - CSS:层叠样式表 | MDN (mozilla.org); 不同的标签, 对于指定的元素可以对自己属性的设置默认值.
好在用户只需要显式定义需要的值就可以覆盖默认值(默认值的优先级是最低点)
CSS属性继承
具体来说是CSS某个具体属性的继承, 当元素的一个继承属性(inherited property)没有指定值时,则取父元素的同属性的计算值 computed value。只有文档根元素取该属性的概述中给定的初始值(initial value)(这里的意思应该是在该属性本身的定义中的默认值)。
这里涉及CSS设置样式的几个全局值(所有的属性都可以设置这几个值)
/* 全局值 */
color: inherit;
color: initial;
color: revert;
color: revert-layer;
color: unset;
细节请看文章:CSS的全局值 initial inherit revert overlay unset在CSS中,全局值是一组特殊的值 - 掘金 (juejin.cn)
当CSS的某个属性被设置为inherit时, 他将继承父组件的样式(不一定是显式定义的样式,而是最终在页面中显示的样式), CSS中许多属性被默认设置为inherit, 比如div的width、color等.
CSS生效的优先级
到此我们把能影响到HTML元素样式的所有情况都讲到了: HTML默认样式(CSS默认值)、CSS继承、内联样式、内部样式、外部样式.
其中内部样式和外部样式的优先级都依赖于选择器, 它们只是样式文本内容所保存的地方不一样, 在优先级上没有差别. 结果为:
- 基础优先级: 默认样式 < 标签选择器
div< 类选择器.students< ID选择器#xiaoming - 级联优先级:
div .name、.name中, 由于级联选择器的优先级可以两两叠加, 所以div .name更高 - 执行优先级: 两个选择器优先级相同, 哪一个样式写在后面, 哪一个优先级高
- 覆盖优先级:
!important最高优先级, 在声明后添加该关键字, 强行提升优先级到最高, 一般情况下不建议使用
四个优先级之间的对比: 执行优先级 < 级联优先级 < 基础优先级 < 覆盖优先级
层叠层(级联层)@layer
层叠层是CSS开放给开发者的一个新特性. 让我们可以更容易去管理大量样式的优先级.
怎么理解@layer呢, @layer让开发者对自己写的样式可以再进一步分组. 然后每一组有独立的优先级.
具体语法看这里: 层叠层 - 学习 Web 开发 | MDN (mozilla.org)
重构优先级理论
同时我们也可以使用层叠层的概念, 新瓶装旧酒. 重新整理样式的优先级问题. (不用惊讶, 科学都是重复推倒重来. 事实永远在那里, 但是怎么理解都可以, 只要越贴近越好, 我们只是在模拟)
我们可以在浏览器影响页面效果的样式也按照层叠层理论做出分层(只是在学), 优先级由上往下: 从低到高
- 用户代理普通样式(浏览器默认样式)
- 用户普通样式(网站访问者:通常是通过浏览器的设置或扩展应用的。用户可以根据自己的喜好来修改网页的外观)
- 作者普通样式(开发者)
- 正在动画的样式(正在运行的帧动画)
- 作者重要样式(开发者
!important) - 用户重要样式(网站访问者
!important) - 用户代理重要样式(网站访问者
!important) - 正在过渡的样式(正在运行的
transition)
这里的优先级排序更为完整, 考虑得更为全面: 比如对前面提到的浏览器默认样式再一次细分为用户代理普通样式和用户. 对于正在执行的动画样式, 正在执行的过渡样式的优先级也做了对比.
@layer可以进一步对作者普通样式(开发者) 层再分层. 根据上面的优先级图, 可以知道!important的优先级高于@layer.
值和单位
截止到当前, 我们讨论完了样式的生效原则, 对着文章开头的示例
h1,h2,h3 {
margin: 0 0 1px 0;
}
我们讲完了h1,h2,h3 选择器部分, 明确了如何准确的把样式应用到某个具体的元素的方法. 接下来需要讲的是怎么去设置元素的具体的样式, 对应的是示例中的{}内部的这一块内容margin: 0 0 1px 0; 文章开头提到, 这一段声明语句用于设置元素的外边距. 我们接下来详细的看看如何设置各种样式吧.
其中的margin是代指某个样式的属性名, 而0 0 1px 0是属性的值, 合起来就是就是一条完整的声明语句.每一个样式一条声明语句, 每一个声明语句后面需要加;
上面的例子, 如果你想设置多个样式的应该是这样的, 比如要在添加一下字体大小:
h1,h2,h3 {
margin: 0 0 1px 0;
font-size: 16px;
}
每一个样式一条声明语句, 每一个声明语句后面需要加;
全局值
上面说CSS属性继承的时候说到了.
值的写法
- 单词或数字:
red、3、3px - 使用空格隔开的单词列表(上面的例子就是):
0 0 1px 0 - 函数,不仅选择器有函数, 属性的值也有函数.
background-image: url('path/to/image.jpg');
单位
在CSS中,单位用于指定属性的尺寸、长度、角度等值。以下是CSS中常用的单位列表及其介绍: 值与单位-MDN
盒模型与排版
HTML是由一个个标签组合起来的, 很多标签内部还可以放其他标签, 如div、p等, 一般称为容器; 有些标签不能再往内部放内容了, 如img、input等. 可以在页面展示出来的标签都可以被称为盒子. 盒子的构造被称为盒模型.
简单说一下盒子的组成: 内容(content) 、内边距(padding)、 边框(border)、 外边距(margin).
图片来自: 更多有关盒子模型的信请看盒模型(里边有在线示例可以用哦)-MDN
看完上面文章, 应该可以很细致的控制盒子的每条边的样式,熟悉使用盒子的边框和内外边距等属性. 其中除了margin可以是负数以外, 其他属性最小值为0, 单位为距离单位. 这里特别提一下marigin为负值的情况, 可以这样理解, 当值大于0时, 是把相邻的元素往外推, 当为负值时,是把相邻元素往自己内部拉
一般认为盒子仅由这四部分组成, 其实还有一部分叫轮廓outline, 他在border外,margin之上(它不占用空间, 可以理解为是浮在margin之上的).
盒子的两种尺寸设计
// 默认盒子
box-sizing: content-box;
// 替代盒子
box-sizing: border-box;
默认盒子在设置宽高时, 影响的是内容区content的宽高, 而替代盒子设置宽高时, 影响的是边框区border的宽高.
盒模型的种类
为了满足多样化的业务需求, 存在很多种盒子, 不同盒子在展示上存在各自的特点. 接下来我们就深入的了解它们:
首先了解一个CSS属性display, 它可以让用户手动更改元素的为各种类型的盒子.比如
// 这可以把HTML的任意在页面上展示的元素改为 区块盒子(div默认的盒子类型)
display: block;
区块盒子
平时使用的最多的盒子之一,div元素默认为区块盒子
行内盒子
display:inline;
- 盒子不会产生换行(这里指的是它作为元素, 不会导致在父节点产生换行, 但是它内部的内容在文本太长会换行,
<br/>等能换行)。 width和height属性将不起作用。- 垂直方向(
left、right)的内边距、外边距以及边框会被应用但是不会把其他处于inline状态的盒子推开。 - 水平方向(
top、bottom)的内边距、外边距以及边框会被应用且会把其他处于inline状态的盒子推开。
如 <a>、 <span>、 <em> 以及 <strong>,默认使用 inline 作为外部显示类型
行内区块
介于区块和行内的中间体
display:inline-block
行内区块还是不会导致在父元素内换行, 但是它允许设置尺寸和边距.
弹性盒子
display:flex;
现有很完善的文章: 弹性盒子-MDN
网格盒子
display:grid
现有很完善的文章:网格-MDN
浮动float
当元素设置了float时, 会被提取到父标签的左侧(float:left)或右侧(float:right), 然后对后续所有节点的内容排版产生影响(所有内容遇到该元素都需要让出位置,具体怎么让由后续元素自己决定), 会衍生到文档结束, 除非有元素使用clear属性清除浮动行为. 具体参见下文:
定位position
可使元素固定在指定位置, 不受其他内容影响 定位-MDN
多列布局column-count、column-width
可以像报纸一样多列排版, 是一个相对较早的实现的规范. 详细看这里: 多列布局-MDN
样式多端兼容、响应式布局、媒体查询
Web网站可在多种类型设备上浏览, 包括但不限于: 电脑、手机、平板. 不同类型的设备的屏幕尺寸千差万别, 一个网站可能在电脑上显示得很好, 在手机上乱七八糟. 怎么解决这个问题呢? 就是本届需要考虑的内容.
主流方案有两种: 相对尺寸, 媒体查询, 一般在具体使用的场景中, 这两种方法可以互为补充, 同时在项目中使用.
相对尺寸
前面在讨论属性值的时候有专门讨论过值的单位. 相对尺寸用于响应式布局就是值的单位在具体场景中的应用. 主要涉及到以下单位: %、em、rem、vw、vh. 使用它们可以让定义元素的尺寸根据屏幕视窗的大小、父容器的大小等来进一步动态展示宽度. 达到兼容不同大小屏幕的目的.
这里有一篇相关文档可查看: 响应式设计
媒体查询@media
相对尺寸目标是让我们可以使用同一套样式兼容各种设备的尺寸需求, 但是这样的方法在很多场景不能够尽善尽美. 这时候人们就考虑在不同的设备上应用不同的样式, 这就是媒体查询的由来. @media可以查到当前运行的设备的具体类型. 如果我们针对不同的设备写不同的样式, 比如电脑写一份, 手机写一份, 两者可以避免干扰,达到兼容的目的.
详细指南看这份文档: 媒体查询入门指南-MDN
看完入门还需要进一步深入可以看这篇文档: 这里提供完整的API: 媒体查询:MDN
字体个性化
字体可谓是Web的核心内容之一. 人们依赖文本, 却不喜欢文字. 看多容易犯困, 知识只能写入文章, 却难入心神. 所以现在的Web, 总是给文字周围添加各种各样的其他内容, 比如线线框框、图片视频. 到头来还是离不开文字.
接下来讨论如何给网站应用上精美的字体. 这涉及到两个方面:字体排版, 字体更换
字体排版
字体调整的各种用法: 基本文本和字体样式 - 学习 Web 开发 | MDN (mozilla.org)
字体更换
本篇内容涵盖了安装和使用自定义字体的基本内容. Web 字体 - 学习 Web 开发 | MDN (mozilla.org)
动画与过渡
前端开发者之间炫技, 那丝滑的动效是必不可少的. 这里主要讨论CSS里的动效实现.
什么CSS属性可以使用动效呢?
并不是所有的CSS属性都可以使用动效, 只要可数量化表示的属性可以使用动效: 比如尺寸相关的width、height、margin、position等. 颜色color也是可以的, 透明度opacity也是可以的
而像display、font-family这类使用枚举型的值就不行.
所以我们在定义动画的时候, 一般只修改可量化的部分的属性值. (如果定义的时候, 两种值都包含了会如何? 一般会在动画开始时闪一下,因为枚举值会被直接使用)
过渡transition
动画animation
CSS语言拓展
CSS是可以被浏览器直接解析并执行的语言, 开发者写完之后, 浏览器直接可用. 但在前端长时间的发展中, 开发者们总结了许多编写的经验, 提出了许多可以精简代码量的方案. 其中一类就是CSS语言拓展. 流行的三个SASS、SCSS和LESS
既然说是拓展, 那就是附加一些新东西, 所以SCSS和LESS除了提出一些新语法, CSS自带的所有语法都是完全支持的. SASS略有不同. SASS采用了一套新语法, 代码量上更为简洁. 新手使用的话需要进一步的适应.
SASS和SCSS由同一个库提供支持, LESS是独立的库, 一般以.sass结尾的文件语法为SASS, .scss是SCSS,.less是LESS
而有这些拓展语言编写的代码还是会被相关的库编译成CSS后浏览器才能使用.
当前项目(2024)一般都会选用SCSS或LESS, 而不是直接使用CSS.
SASS语言拓展
提供了新功能, 让在组织CSS, 复用样式等方面都有新的可能.
- 变量
- 嵌套
- 模块
- 混入
- 继承
- 计算方法
相关语法请看:
优先看官方文档, 第三方教程可能在版本更新新特性时不能及时更新.
LESS语言拓展
作为SASS的竞品, LESS在设计上和在很多地方都是类似的, 但是在语法上他只支持类似.scss的语法, 不支持.sass这种更精简的语法, 如果你希望语法上更简洁, 那就只能使用SASS.
- 变量
- 嵌套
- 模块
- 继承
- 混入
- MAPs(变量对象)
同样上官网语法教程: Features In-Depth | Less.js (lesscss.org)(英文 | 上翻译)(lesscss.org/features/#s…)