CSS-预热篇

392 阅读7分钟

这是一个系列的文章,你也可以查看其他文章:

0、CSS-预热篇

1、CSS(一)详解position

2、CSS(二)transform

3、CSS(三)flex布局(flex弹性布局详解)

4、CSS(四)详解Grid布局

5、CSS(五)CSS动画-transition简介

6、CSS(六)CSS动画-animation简介

7、CSS(七)两栏布局详解

8、CSS(八)三栏布局详解

9、CSS(九)垂直居中详解

最近听了winter的极客时间 专栏关于css的讲解,深感自己的css基础较为薄弱,所以打算最近将css的重要东西做一个总结。

首先学习css需要到W3C的网站,在这里会发现有很多css相关标准,去掉Working Draft状态的标准,切换标准状态下拉框,得到候选标准为13,候选标准为23,(数据一直在变化,截止20190808数据)。

css语法的最新标准为:www.w3.org/TR/css-synt…在这里你能找到关于css的最新语法标准。这篇文档比较详细,包含css的简介、描述、标记和解析css,以及css的分类。

从文档我们知道css语法规则分为两类:一是带@的规则(at-rule),二是普通规则(qualified rule)。

一、at-rule

由@关键字和后续的一个区块组成,如果没有区块,则以;结束。实际开发中使用较少。

@charset 字符编码规则

@charset "utf-8";

@import 引入一个css文件

@import [ <url> | <string> ]
        [ supports( [ <supports-condition> | <declaration> ] ) ]?
        <media-query-list>? ;

@media 媒体查询对设备类型判断

@media print {
    body { font-size: 10pt }
}

@page 分页媒体访问网页的表现

@page {
  size: 8.5in 11in;
  margin: 10%;

  @top-left {
    content: "Hamlet";
  }
  @top-right {
    content: "Page " counter(page);
  }
}

@counter-style 定义列表项表现,出firefox部分支持外,其他浏览器都不支持。可以上 https://caniuse.com 搜索@counter-style查看浏览器的兼容情况。

@counter-style triangle {
  system: cyclic;
  symbols: ‣;
  suffix: " ";
}

@keyframes 定义动画关键帧

@keyframes diagonal-slide {

  from {
    left: 0;
    top: 0;
  }

  to {
    left: 100px;
    top: 100px;
  }

}

@fontface 字体相关

@font-face {
  font-family: Gentium;
  src: url(字体url);
}

p { font-family: Gentium, serif; }

@supports 检查环境特性

@namespace 定义命名空间

@viewport 定义视口特性

除此之外,还有些目前不太推荐使用的at规则

color-profile是SVG1.0引入的CSS特性,但是几乎没什么浏览器实现

@document还没实现,可能会出现在CSS4中

@font-feature-values

二、普通规则

主要由选择器和声明列表构成。

1、选择器列表(www.w3.org/TR/selector…),它属于CSS和HTML共用标准。

这篇文档Grammar中列出了目前选择器语法:

<selector-list> = <complex-selector-list>

<complex-selector-list> = <complex-selector>#

<compound-selector-list> = <compound-selector>#

<simple-selector-list> = <simple-selector>#

<relative-selector-list> = <relative-selector>#


<complex-selector> = <compound-selector> [ <combinator>? <compound-selector> ]*

<relative-selector> = <combinator>? <complex-selector>

<compound-selector> = [ <type-selector>? <subclass-selector>*
                        [ <pseudo-element-selector> <pseudo-class-selector>* ]* ]!

<simple-selector> = <type-selector> | <subclass-selector>


<combinator> = '>' | '+' | '~' | [ '|' '|' ]

<type-selector> = <wq-name> | <ns-prefix>? '*'

<ns-prefix> = [ <ident-token> | '*' ]? '|'

<wq-name> = <ns-prefix>? <ident-token>

<subclass-selector> = <id-selector> | <class-selector> |
                      <attribute-selector> | <pseudo-class-selector>

<id-selector> = <hash-token>

<class-selector> = '.' <ident-token>

<attribute-selector> = '[' <wq-name> ']' |
                       '[' <wq-name> <attr-matcher> [ <string-token> | <ident-token> ] <attr-modifier>? ']'

<attr-matcher> = [ '~' | '|' | '^' | '$' | '*' ]? '='

<attr-modifier> = i

<pseudo-class-selector> = ':' <ident-token> |
                          ':' <function-token> <any-value> ')'

<pseudo-element-selector> = ':' <pseudo-class-selector>

经过我的整理,目前选择器主要有以下几类:

(1)基本选择器

主要是*(通用选择器)、tag(html标签)选择器、.(类选择器)、#(id选择器)。

(2)组合选择器

E,F:多元素选择器,同时匹配所有E元素或F元素

E F:后代选择器,匹配所有属于E元素后代的F元素

E>F:子元素选择器,匹配元素E的所有后代F元素

E+F:相邻元素选择器,匹配所有紧随E元素之后的同级元素F(易错)

E~F:兄弟选择器,匹配E元素后的所有F元素

E||F:列选择器,匹配table中E(col)列的F(td)格,目前浏览器还不支持

col.selected || td {
  background: gray;
  color: white;
  font-weight: bold;
}
<table>
  <col span="2">
  <col class="selected">
  <tr><td>A <td>B <td>C
  <tr><td colspan="2">D <td>E
  <tr><td>F <td colspan="2">G
</table>

(3)属性选择器

E[att]:匹配所有具有att属性的E元素,不考虑它的值。(注意:E在此处可以省略,比如"[cheacked]"。以下同。)

E[att=val]:匹配所有att属性等于"val"的E元素

E[att~=val]:匹配所有att属性具有多个空格分隔的值、其中一个值等于"val"的E元素

E[att|=val]:匹配所有att属性具有多个连字号分隔(hyphen-separated)的值、其中一个值以"val"开头的E元素,主要用于lang属性,比如"en"、"en-us"、"en-gb"等等

E[att^="val"];属性att的值以"val"开头的元素

E[att$="val"]:属性att的值以"val"结尾的元素

E[att*="val"]:属性att的值包含"val"字符串的元素

(4)伪类选择器

E:enabled:匹配表单中激活的元素

E:disabled:匹配表单中禁用的元素

E:checked:匹配表单中被选中的radio(单选框)或checkbox(复选框)元素

E::selection:匹配用户当前选中的元素

E:root:匹配文档的根元素,对于HTML文档,就是HTML元素

E:nth-child(n):匹配其父元素的第n个子元素,第一个编号为1

E:nth-child(an+b)

E:nth-last-child(n):匹配其父元素的倒数第n个子元素,第一个编号为1

E:nth-of-type(n):与:nth-child()作用类似,但是仅匹配使用同种标签的元素

E:nth-last-of-type(n):与:nth-last-child() 作用类似,但是仅匹配使用同种标签的元素

E:last-child:匹配父元素的最后一个子元素,等同于:nth-last-child(1)

E:first-of-type:匹配父元素下使用同种标签的第一个子元素,等同于:nth-of-type(1)

E:last-of-type:匹配父元素下使用同种标签的最后一个子元素,等同于:nth-last-of-type(1)

E:only-child:匹配父元素下仅有的一个子元素,等同于:first-child:last-child或 :nth-child(1):nth-last-child(1)

E:only-of-type:匹配父元素下使用同种标签的唯一一个子元素,等同于:first-of-type:last-of-type或 :nth-of-type(1):nth-last-of-type(1)

E:empty:匹配一个不包含任何子元素的元素,注意,文本节点也被看作子元素

E:not(s):匹配不符合当前选择器的任何元素

E:target:匹配特定"id"点击后的效果

E:active:匹配被用户激活的元素

E:visited:匹配被用户激活的元素

E:focus:匹配获得焦点的元素

E:link:匹配被用户激活的元素

E:indeterminate:匹配状态不确定的表单元素,单选框或者多选框中未被选中的元素。

E:hover:匹配PC端上被鼠标悬停的元素。

E:defined:表示任何已定义的元素。这包括任何浏览器内置的标准元素以及已成功定义的自定义元素

E:lang:基于元素语言匹配元素页面

目前所有浏览器尚不完全不支持的伪类选择器还有:

:any-link、:blank、:dir、:has、:host、:host-context()、focus-visible、:matches、:fullscreen、:default、:optional、:scope等

(5)伪元素选择器

::first-line 行选择器,匹配元素的第一行

::first-letter 字母选择器,匹配元素的第一个字母

::before: 元素前插入一个元素

::after:元素后插入一个元素,可用于清除浮动。

2、声明项:包含“key:value”的键值对。

key即属性,value即值。

一个常见的css声明项:

div{
    font-size: 14px;
    color: red;
    background:green;
    border: 1px solid #000;
    ...
}

属性是由中划线、下划线、字母等自称的标识符,CSS中还支持使用反斜杠转移。注意:属性不允许使用连续的两个中划线开头,这样的属性会被认为是CSS变量。

CSS 变量标准(www.w3.org/TR/css-vari…)中,以双中划线开头的属性会被当做变量,与之配合的则是var函数。

我们可以通过在浏览器console中以下语句获取浏览器实现了哪些属性(去掉webkit前缀):

Object.keys(document.body.style).filter(e => !e.match(/^webkit/))

目前是390个属性。

winter老师给出了一个简易爬虫去爬取我们获取的属性值。

var iframe = document.createElement("iframe");

document.body.appendChild(iframe);

iframe.src = "https://www.w3.org/TR/2019/WD-css-lists-3-20190425/"

function happen(element, type){
  return new Promise(resolve => {
    element.addEventListener(type, resolve, {once: true})
  })
}

happen(iframe, "load").then(function(){
  //Array.prototype.map.call(document.querySelectorAll("#container li[data-tag~=css] h2"), e=> e.children[0].href + " |\t" + e.children[0].textContent).join("\n")
  console.log(iframe.contentWindow);
})
async function start(){
  var output = []
  for(let standard of  Array.prototype.slice.call(document.querySelectorAll("#container li[data-tag~=css] h2:not(.Retired):not(.GroupNote)"))) {
    console.log(standard.children[0].href);
    iframe.src = standard.children[0].href;
    await happen(iframe, "load");
    var properties = Array.prototype.map.call(iframe.contentWindow.document.querySelectorAll(".propdef [data-dfn-type=property]"), e => e.childNodes[0].textContent);
    if(properties.length)
        output.push(standard.children[0].textContent + " | " + properties.join(", "));
  }
  console.log(output.join("\n"))
}
start();

CSS值标准(w3.org/TR/css-valu…

值可能是以下类型:

css范围关键字(如initial、unset、inherit等)、字符串、url、整数/实数、维度、百分比、颜色、图片、2D位置,函数等。这其中函数部分值得重点关注。

按照函数功能,分成以下 5 个类别(可能并不完全准确),但是除repeat、transform中的函数、var、calc等外其中大部分函数浏览器目前都不支持,近期会测试以下函数的支持情况。
# 1. 图片
* filter
* blur()
* brightness()
* contrast()
* drop-shadow()
* grayscale()
* hue_rotate()
* invert()
* opacity()
* saturate()
* sepia()
* cross-fade()
* element()
* image-set()
* imagefunction()

# 2. 图形绘制
* conic-gradient()
* linear-gradient()
* radial-gradient()
* repeating-linear-gradient()
* repeating-radial-gradient()
* shape()

# 3. 布局
* calc()
* clamp()
* fit-content()
* max()
* min()
* minmax()
* repeat()

# 4. 变形/动画
* transform
* matrix()
* matrix3d()
* perspective()
* rotate()
* rotate3d()
* rotateX()
* rotateY()
* rotateZ()
* scale()
* scale3d()
* scaleX()
* scaleY()
* scaleZ()
* skew()
* skewX()
* skewY()
* translate()
* translate3d()
* translateX()
* translateY()
* translateZ()

# 5. 环境与元素
* var()
* env()
* attr()

参考资料:

1、developer.mozilla.org/en-US/docs/…

2、www.w3.org/TR/css-synt…

3、www.w3.org/TR/?target=…

4、winter极客时间专栏《重学前端》