01.介绍
01.介绍
CSS全名是层叠样式表,用于对html元素或xml元素进行格式化,让同一类型的元素拥有相同的样式- CSS灵感
- animate.css
- CSS布局教程
- 查看样式支持can I use
- MDN文档
- CSS权威指南例子
1.1 如何引入
CSS是通过样式键值对来设置样式的,每条样式都是样式名: 属性值;在
html文件中,主要可以通过三种方法引入CSS样式- 通过
style标签属性引入样式:
<!-- 在style中写css样式 --> <div style=""></div>- 通过在
html文件style标签中写CSS选择器或使用@import引入CSS文件
<style> /* 使用@import引入文件,必须放在开头,比如引入位于服务器根地址的main.css文件 */ @import url('/main.css'); /* 在标签中写选择器,比如删除浏览器默认body外边距 */ body { margin: 0; } </style>- 通过在
link标签引入.css文件使用文件中定义的样式
<!-- 引入style.css文件 --> <link rel="stylesheet" href="style.css">通过http请求头添加
.css文件除了通过
link标签,还可以通过给HTTP添加额外头部,引入CSS文件,这种方法在语义上和link标签引入相同,需要服务器支持,下面是Nginx添加额外头部对所有的页面引入CSS文件的配置,MDN文档location ~* \.(html|htm|xml|php)$ { add_header Link '<http://example.com/additional.css>; rel=preload; as=style'; }- 通过
样式引入的方法有三种,如果一个属性在不同地方定义了不同的样式,将根据引入优先级,决定最终的样式
优先级从低到高排序:
- 引入
CSS文件 - 在
head中通过style定义样式 - 在标签上的
style定义样式
- 引入
1.2 媒体查询
- 创作人员通过媒体查询(
mediaquery)定义浏览器在何种媒体环境中使用指定的样式表,根据指定媒体类型的特性选择样式表
1.2.1 媒体查询使用
媒体查询可以在下述几个地方使用:
link元素的media属性style元素的media属性@import声明的媒体描述符部分@media声明的媒体描述符部分
<link href="print-color.css" type="text/css" media="print and (color)" rel="stylesheet"> <style type="text/css"media="screen,print"></style> <style> /* 在css部分定义 */ @import url(print-color.css) print and (color); @media screen,print {} </style>媒体查询可以是简单的媒体类型,也可以是复杂的媒体类型和媒体特性描述符的组合
/* 其中mediatype是媒体类型,mediafeature是媒体特性描述符 */ @media not|only mediatype and (mediafeature and|or|not mediafeature) { /* 在满足条件的媒体中使用的样式 */ }媒体类型有以下几种:
all:用于所有设备(默认)print:用于打印机和打印预览screen:用于电脑屏幕,平板电脑,智能手机等speech:应用于屏幕阅读器等发声设备
媒体特性描述符:
值 描述 width输出设备中的页面可见区域宽度 height输出设备中的页面可见区域高度 orientation输出设备中的页面可见区域高度是否大于或等于宽度 aspect-ratio输出设备中的页面可见区域宽度与高度的比率 color输出设备每一组彩色原件的个数。如果不是彩色设备,则值等于0 color-index在输出设备的彩色查询表中的条目数。如果没有使用彩色查询表,则值等于0 monochrome在一个单色框架缓冲区中每像素包含的单色原件个数。如果不是单色设备,则值等于0 device-aspect-ratio输出设备的屏幕可见宽度与高度的比率 device-height输出设备的屏幕可见高度 device-width输出设备的屏幕可见宽度 resolution设备的分辨率。如:96dpi,300dpi,118dpcm scan电视类设备的扫描工序 新的支持
其他媒体特性描述符见媒体特性 上面列出的结果是数值的特性(只有
scan结果不是数值)都支持max-和min-前缀,分别表示不大于和不小于此大小的情况下应用对应的规则 在CSS4中允许通过width使用比较符实现之前的max-width等功能,更直接/* 在CSS3为页面宽度小于30em的时候设置样式 */ @media (max-width: 30em) { } /* 在CSS4实现 */ @media (width <= 30em) { }联合构造:
not、and、,和only可用于联合构造复杂的媒体查询,将它们组合为一个规则not:表示选择不满足之后的设置的添加的设备,not的优先级最低,因此在开头使用not,将表示否定所有的条件only:对较早的浏览器而言,如果同时使用媒体类型和媒体特性构造符,会简单解释为媒体类型查询,忽略其他部分,使用only可以使整个查询匹配才应用样式,只能用在开头and:用于将多个媒体查询规则组合成单条媒体查询,:将多个媒体查询合并使用一个规则
1.2.2 特性查询
CSS允许根据用户代理是否支持特定的样式和属性值来应用样式,这个功能称为特性查询特性查询在结构上与媒体查询很像,假设我们想在用户代理支持
color属性时(显然是支持的)为元素设定颜色,可以这样写:/* 如果能识别并处理color: black 这样的样式就应用这段配置 */ @supports (color: black) { body {color: black; } }结合媒体查询使用
特性查询本身支持嵌套,当然也可以嵌套在媒体查询中,也可以反过来嵌套,并支持媒体查询联合构造符
@media screen and (max-width:30em) { @supports (color:black) and ((display:flex) or (display:grid)) { /*相关的样式*/ } }
1.2.3 优先级
媒体查询并不会改变选择器的优先级,将遵循CSS规则,同样的选择器里面同样的规则,定义在后面样式将覆盖之前定义的样式
如果希望使用媒体查询修改特定情况的样式,需要将媒体查询放在最后
将媒体查询在全局样式之前定义<span>最终字体颜色一直为绿色</span>@media (max-width: 100vh) { span { color: red; } } span { color: green; }
1.2.4 分页媒体
分页媒体是通过一系列单独的页面显示文档的媒体,这与
screen是不同的,print就是分页媒体print打印件除了与screen屏幕有物理形态上的差异,还有样式的区别- 大多数设计人员都认为使用衬线字体打印效果最好,无衬线字体更适合显示
- 打印时会偏向于打印机的字体大小,比如
pt - 大多数情况下,浏览器打印时禁止打印背景
/* 比如打印时使用 */ body {font: 12pt "Times New Roman", "TimesNR", Times, serif;}在分页媒体中还需要处理多栏布局的问题,有时可能要把内容还原成一栏或让某些部分不显示
设置页面大小:
CSS把打印页面定义为一个页面框,一个页面框由两部分组成- 页面区域,即内容在页面中占的部分,和常规元素的内容框是对等的,页面区域的边界是初始包含块
- 外边距区域,位于页面区域的四周

页面框 页面大小通过
@page设置,@page块是和媒体查询@media差不多的块,size在这里才有意义size可以定义最多两个长度值,分别对应宽和高,如果只有一个,则宽高相同支持关键字
landscape水平打印和portrait垂直打印支持大量预定义纸张关键字
关键字 说明(尺寸先宽后高) A5148 mm x 210 mm (5.83 in x 8.27 in) A4210 mm x 297 mm (8.27 in x 11.69 in) A3297 mm x 420 mm (11.69 in x 16.54 in) B5176 mm x 250 mm (6.93 in x 9.84 in) B4250 mm x 353 mm (9.84 in x 13.9 in) JIS-B5182 mm x 257 mm (7.17 in x 10.12 in) JIS-B4257 mm x 364 mm (10.12 in x 14.33 in) letter8.5 in x 11 in (215.9 mm x 279.4 mm) legal8.5 in x 14 in (215.9 mm x 355.6 mm) ledger11 in x 17 in (279.4 mm x 431.8 mm)
@page {size: 7.5in 10in; margin: 0.5in; } /* 可以提供具名页面,之后在某些元素使用 page:rotate; 选择使用此页面打印对应的部分 */ @page rotate {size: landscape; margin: 0.5in; } /* 可以使用伪类选择某些页面 */ @page :first {margin-left: 3cm; margin-right: 5cm; } /* 在打印书籍左侧的页面 */ @page :left {margin-left: 3cm; margin-right: 5cm; }分页:如果希望在特定的情况下分页,可以使用
page-break-before和page-break-after- 初始值
auto:不强制分页 always:强制分页left:确保元素在左侧页面right:确保元素在右侧页面avoid:尽量避免在元素前后分页,还有一个page-break-inside与这个效果一样,接收auto(初始值)或avoid(尽量避免在元素内分页),这些都只能尽量避免
/* 希望在h1之后和h2之前分页,同一个位置只会分页一次 */ h1 { page-break-after: always; } h2 {page-break-before: always; }- 初始值
设置孤行:
widows和orphans可用于块级元素widows设置元素分页时至少应该有多少行出现在页面顶部,默认为2,如果不满足,会在段落特定位置插入分页符orphans设置元素分页时至少应该有多少行出现在页面底部,默认为2,如果不满足会在段落前面插入分页符
分页行为可能被避免
avoid定位元素的打印影响
定位元素可以被打印,但要注意
- 基于初始包含块
fix定位元素会在每一页的对应位置显示,可以用来设置每页都有的页头 absolute定位的元素如果超过了当前已有纸张的显示区域,用户代理可能会进行裁切,或为了显示生成额外空白页
1.3 选择器
- 元素选择器通常用于选择
html元素,快速为它们修改样式- 在最早的时候,只能通过在标签上写style修改样式,如果需要频繁修改样式,一定是很累人的事
- 现在对同一批元素的样式修改可以通过选择器批量完成
1.3.1 基础的选择器
在选择器中最基础的就是选择某类元素的选择器了,这些选择器一般是在
html中预定义的某个元素,比如:div、h1、p,这些都是html常用的标签名,只要使用的是这种标签名,就会应用样式对于xml文件而言,同样通过这种方式选择对应的标签
/* 为body设置样式,删除默认的外边距 */ body { margin: 0; }对于IE9之前的浏览器,他们无法识别之后添加的标签并提供样式,因此,如果需要兼容老版本浏览器,需要使用
document.createElement('标签名')创建标签在
html文件中,如果希望将一些元素按自己的方式选择出来,可以考虑使用标签上的class属性,然后通过类选择器选择对应的类/* 如果class="red",希望选择red类为其设置字体颜色为红色 */ .red { color: red; }同样的,也可以利用标签上的
id属性,通过id选择器选择对应的标签对于样式而言,重复的id都会有相同的样式,但id一般用于js选择,每次只会选择第一个有id属性的标签,因此还是不建议使用重复id
/* 如果id="submit-button",修改字体大小为18px */ #submit-button { font-size: 18px; }如果希望为不同选择器设置相同样式可以用
,分隔选择器,同时设置样式/* 为h1,h2,p设置相同样式,将它们的字体颜色修改为白色 */ h1, h2, p { color: white; }如果希望添加对所有标签生效的样式,可以使用通配符
** { color: red; }
1.3.2 父子兄弟选择器
除了基础的选择器,还有通过文档结构的选择器,主要用于选择某元素的父子兄弟元素的选择器
html或xml文档结构可以看成树状的层次结构,在最外层的标签是根结点,包裹第二层标签结点,根据包裹构建树状结构后代选择器:用于选择某些元素的后代元素,修改样式
- 注意:如果希望对一个元素使用多个约束,中间不需要加空格,比如:
div.red选择有red类的div标签
/* 把作为h1的后代em元素的字体颜色设置为灰色 */ h1 em { color: grey; } /* 允许进行多次选择,进行更多的限制 */ ul ol ul li { color: grey; }- 注意:如果希望对一个元素使用多个约束,中间不需要加空格,比如:
选择子元素:与选择后代不同的是,子元素只是下一层的标签结点
/* 为h1的直接子代设置红色字体 */ h1 > strong { color: red; }选择兄弟元素:兄弟元素是和元素具有相同层级且同属一个父元素的元素
- 选择方法有两种,选择跟在此元素之后的所有兄弟元素
~和选择跟着此元素之后的第一个兄弟元素+
/* 选择所有h2后续的兄弟元素ul,设置为斜体字体 */ h2 ~ ul { font-style: italic; } /* 选择p元素接下来的第一个兄弟元素a,设置为红色字体 */ p + a { color: red; }- 选择方法有两种,选择跟在此元素之后的所有兄弟元素
选择父元素:这不是直接支持的选择器,但可以通过伪类或
js实现js能够方便地获取到所有需要修改的元素,并通过parentNode访问到父元素,能够方便地修改样式- CSS伪类:has()能够对当前元素的相关元素进行判断,判断可以直接通过子选择器和兄弟选择器实现
/* 如果a标签中有img元素,则设置为block布局 */ /* 通过这种方法可以选择img的父元素a */ a:has(img) { display: block; }选择之前的兄弟元素:这也不是直接支持的选择器,和选择父元素一样,可以通过伪类或
js实现js能够方便地获取到所有需要修改的元素,并通过previousElementSibling访问到前一个兄弟元素,如果不存在前一个兄弟元素,则获取到nullCSS伪类:has(),和上面获取父元素方法一样,判断直接通过兄弟选择器实现
/* 如果a标签接下来的第一个元素是p,则设置为红色字体 */ a:has(+p) { color: red; }
1.3.3 标签属性选择器
在
CSS3允许通过标签属性进行筛选,有以下几种选择方式,E可以省略(选择相对于所有元素*生效)E[attr]:选择有对应属性的标签E[attr="val"]:选择对应属性为此值的标签E[attr*="val"]:选择对应属性有该值的标签E[attr^="val"]:选择对应属性以此值开头的标签E[attr$="val"]:选择对应属性以此值结尾的标签E[attr~="val"]:选择对应属性按空格分割能分割到该值的标签E[attr|="val"]:选择对应属性以此值开头的标签,用于lang属性的前缀匹配,要求匹配的值必须和属性的内容相同或匹配到第一个-终止,比如:en能匹配en或en-这样的开头,不能匹配english
/* 选择有required属性的input元素 */ input[required] { color: red; } /* 选择有type为text的input元素 */ input[type="text"] { width: 300px; } /* 选择有href包含example的标签元素 */ a[href*="example"] { font-size: 2em; } /* 选择href以https开头的标签元素 */ a[href^="https"] { font-size: 2em; } /* 选择href以.json结尾的标签元素 */ a[href$=".json"] { font-size: 2em; } /* 将href以空格分割,分割列表中存在example的标签元素 */ a[href~="example"] { font-size: 2em; }
1.3.3 选择器的拼接
在
CSS中,每次选择实际上是限定选择的元素范围,选择器是支持拼接,相当于是不断添加新的限制条件,减小选定的范围,之后的伪类也是支持拼接的/* 带external类以footercopyright作为id且被访问过的a标签 */ a.external#footercopyright:visited {background: gray; } /* 带external类或以http开头的未访问过的a标签 */ a.external:link,a[href^="http"]:link {color: slateblue; }
1.4 伪类
- 伪类大多数都是结构上的,用于快速指代对应的文档中的标签,相当于通过内定义的幽灵类吸附在某些元素上,达到选择某些元素的效果
需要注意的是伪类一般是对元素本身做出限制,即对应伪类是否吸附在此元素上,也就是说筛选满足对应条件的元素,不是选择元素的父子兄弟元素
1.4.1 结构伪类
伪类都是作用在本元素上的
比如:li:last-child是选择作为最后一个子元素的li标签,而不是选择li的最后一个子元素
- 选择根元素
:root:单独使用可以选择html标签,相当于给html标签设置样式 - 选择空元素
元素:empty:比如p:empty可以选择空的p标签这是将文本(伪元素)结点也作为结点的伪类,其他未说明的伪类都不将文本作为结点
- 选择作为唯一子代的元素
元素:only-child:这里的唯一子代的元素意思是对应父元素仅有这一个子元素,比如p:only-child可以选择作为唯一子代的p标签(不一定是父子关系) - 选择唯一的子代元素
元素:only-type:这里的唯一的子代元素意思是某元素在对应元素的子代中只出现一次,一般需要配合后代选择符号加以限制,比如p> img:only-type可以选择p元素的唯一的子代img标签 - 选择第一个和最后一个子元素
元素:first-child和元素:last:child:以前这种要求需要额外设置单独类,但现在已经可以由伪类实现,两个伪类合在一起就相当于only-child了 - 选择第一个或最后一个某种元素
元素:first-of-type和元素:last-of-type:作为父元素的第一个或最后一个对应标签子元素
- 选择某些位置子代元素
元素:nth-child(表达式):选择到满足条件的作为其他元素子代的元素,表达式支持一维多项式an+b或even偶和odd奇关键字,比如ul > li:nth-child(3n + 1)选择第个li元素() - 从后往前选择某些位置子代元素
元素:nth-last-child(表达式):与上面不同的是,此伪类从后往前选取元素 - 选择某些某种类型子代元素
元素:nth-of-type():和选择某些位置类似,不一样的在于会略过其他元素,只对某些类型的子代元素排位,比如p > a:nth-of-type(even)选择偶数位的链接标签,nth-of-last-type从后往前选择使用提示
这部分的伪类都是选择子代,在使用时应该在前面或后面添加其他限制条件
1.4.2 动态伪类
- 除了结构相关的伪类外,还有根据渲染后的页面变化而变化的伪类
- 超链接伪类:
:link指代用作超链接的锚记(即具有href属性),而且指向尚未访问的地址:visited指代指向已访问地址的超链接。出于安全考虑,能应用到已访问链接上的样式十分有限
限制
为了对已访问链接进行隐私保护,现在只能将颜色相关的属性应用到已访问的链接上,包括:
color、background-color、column-rule-color、outline-color、border-color,以及各边的边框颜色属性(例如border-top-color)相关资料
为了对访问链接的隐私进行保护,防止
js读取,:link定义的样式已经应用到所有的链接之上,而且如果通过DOM查找样式,无论是否访问,获取到的都是未访问时的样式 - 用户操作伪类:
:focus:指代当前获得输入焦点的元素,即可以接受键盘输入或以某种方式激活:hover:指代鼠标指针放置其上的元素,例如鼠标指针悬停在超链接上active::指代由用户输入激活的元素,例如用户单击超链接时按下鼠标按键的那段时间
1.4.3 UI状态伪类
UI状态伪类根据用户界面元素的当前状态应用样式UI状态伪类说明 :enabled指代启用的用户界面元素(例如表单元素),即接受输入的元素 :disabled指代禁用的用户界面元素(例如表单元素),即不接受输入的元素 :checked指代由用户或文档默认选中的单选按钮或复选框 :indeterminate指代既未选中也没有未选中(不确定状态)的单选按钮或复选框:这个状态只能由 DOM脚本设定,不能由用户设定:default指代默认选中的单选按钮、复选框或选项 :valid指代满足所有数据有效性语义的输入框 :invalid指代不满足所有数据有效性语义的输入框 :in-range指代输入的值在最小值和最大值之间的输入框 :out-of-range指代输入的值不在控件允许值的范围内的输入框 :required指代必须输入值的输入框 :optional指代无需一定输入值的输入框 :read-write指代可由用户编辑的输入框 :read-only指代不能由用户编辑的输入框 实现
:unchecked伪类的效果不知道为什么没有
:uncheckd伪类,如果有需要可以使用:not(:checkd)代替
1.4.4 其他常见伪类
:target伪类:target指的是在浏览器URL最后跟着的片段标识符,比如:https:www.example.com/?user=1#target1中的target1部分,此部分应该要对应一个页面元素的id,浏览器的默认效果是自动切换到对应标签所在位置- 使用
:target伪类可以对片段标识符和id相同的标签进行样式调整
<!-- 如果当前片段标识符为section2,设置红色字体 --> <style> #section2 { margin-top: 100vh; } *:target { color: red; } </style> <!-- 如果希望当前页面添加片段标识符section2 --> <a href="#section2">to section2</a> <!-- 如果有对应片段标识符,字体将修改为红色 --> <section id="section2"> <p>hhhhh</p> </section> <script> // 允许通过hash设置默认片段标识符 // 由于浏览器的特性,在跳转之后,滚动页面,刷新之后位置不会再跳转到对应标签 // 但如果删去片段标识符或通过上方a标签重新跳转是、会重新定位元素 window.location.hash = "section2"; </script>:lang伪类:用于选择有对应的lang标签属性的元素,相当于[href|="val"]/* 选择lang="zh-xx"或lang="zh"的元素,相当于a[href|="zh"] */ a:lang(zh) { color: gray; }:not伪类:用于选择不满足某些条件的元素相关信息
在
:not伪类出现的早期,条件只支持单选择器,如果需要多条件判断需要使用多个:not伪类,目前这些问题得到了解决/* 将有content类的且满足不是a标签、没有b类、不存在c标签属性的元素设置为绿色字体 */ .content:not(a, .b, [c]) { color: green; }:has伪类:用于选择包含某些满足条件的元素的元素,这里的条件可以通过选择器选择注意
伪类
:has()的支持是从2022年开始的,现在主流浏览器已经支持,但仍有一些浏览器和许多老版本浏览器不支持此选择器/* 如果a标签中的第一个子元素是div,则设置a为红色字体 */ a:has(div:first-child) { color: red; }
1.5 伪元素选择符
- 伪元素和伪类很像,为了实现特点效果,在结构中插入特定元素,伪类使用
:,而伪元素使用::相关信息
在
CSS2时期,伪元素选择符和伪类一样使用:,浏览器有对此进行兼容,不过未来伪元素可能不再支持:选择
对开头文本样式进行修改 ::: import
::fist-letter和::fist-line只能用于block元素上,其他布局方法均不支持 :::::fist-letter:对元素内容中的第一个文本字符进行样式设置- 如果在字符之前或之后出现了标点符号,也会一起被修改样式
- 对于部分语言存在特殊判断,特殊判断与浏览器有关
- 目前通过此方法对
SVG格式文本第一个字符设置样式已获得有限支持
::fist-line:对元素内容中的第一行进行样式设置
提示
对::fist-letter和::fist-line,允许的属性有限,不过文本font-、background-和字体颜色都是支持的,具体支持情况查看MDN文档::first-letter允许的属性、::first-line允许的属性
装饰或创建前后缀元素
::before和::after:允许通过content属性插入可生成的内容,并对插入的内容修改样式content:只有这两个伪类定义此属性会修改显示效果,允许的属性主要包括字符串、图片、全局关键字
装饰前后缀元素的示例<main> 这是正文内容 </main>/* 在内容前添加前缀并设置为红色字体 */ main::before { content: "这是" '前缀内容'; margin: 0 1em; color: red; background-color: #ffba10; border-color: black; border-style: dotted; } main { background-color: #5bc8f7; }
1.6 特指度与层叠
1.6.1 特指度
- 我们可以通过不同的方法选择元素,同一个元素可能被两个甚至以上的规则选择,而且每个选择符不相同,但最终每个样式只能显示为一个效果,如何知道哪个样式会胜出呢
- 答案隐藏在每个选择符的特指度中。用户代理会计算每个选择符的特指度,然后将其依附到每个样式声明上。如果两个或多个属性声明有冲突,特指度最高的声明胜出
一个选择符的特指度度由选择符本身的组成部分决定。一个特指度值由四部分构成,。选择符的特指度通过下述规则确定:
- 选择符中的每个
ID选择符为特指度增加0,1,0,0,比如:#id1 - 选择符中的每个类、属性选择或伪类加,比如:
.class1、[href]和:hover - 选择符中的每个元素和伪元素加,比如:
h1和::before - 连结符和通用选择符(包括通用选择符
*)不增加特指度
继承值没有特指度,连全都没有,会被直接覆盖
- 选择符中的每个
特指度比较,排在最前面的值有更高的权值,依次比较每个值,如果相同再比较后面的值,不同根据当前值的大小,有更大当前值的特指度更大
行内样式的特指度
目前见到的特指度都以零开头,因此你可能在想,那一位为什么要存在呢?存在必定有用。那一位是为行内样式声明保留的,行内样式style声明的特指度比其他声明都高
- 在CSS中,如果希望一个值之后再也不能被修改,可以在样式定义的末尾使用
!important可以做出限制,限制之后,该值不会受到其他修改的影响对于大型项目而言,滥用!import将带来很多的麻烦,不建议使用
- 在scss中,可以使用
!default对变量赋值,如果未设置过该变量值,则定义变量,不然不会被赋值 - 动画样式将比所有的非
!important样式的优先级都要高,会覆盖所有的非动画的非!important样式
1.6.2 层叠
层叠是
CSS的一个基本特征,它是一个定义了如何合并来自多个源的属性值的算法,只有属性值声明才会参与层叠,属性的优先级由低到高为优先级 来源 说明 1 用户代理 普通值,不带 !important2 用户 普通值,不带 !important3 页面作者 普通值,不带 !important4 CSS动画属性将覆盖普通值 5 页面作者 带 !important的样式6 用户 带 !important的样式7 用户代理 带 !important的样式8 css过渡 - - 如果优先级相同,将根据特指度进行合并,使用特指度高的属性
- 如果特指度相同,后声明的将覆盖前声明的属性
