条件CSS分类
目前的三个@规则:
@media
@supports
@viewport
CSS的@规则
CSS的@规则是(at-rule)是一条语句,它为CSS提供了执行或如何执行的指令。
@规则以@开头,后面跟相应的关键词,关键词充当标识符。
CSS的@规则分为常规规则和嵌套规则两大类。
常规规则:
语法:@关键词
常见的规则:
@charset 'utf-8'
1,应用于某些CSS属性(content)中使用非ASCII字符或包含UTF—8等非ASCII字符时,@charset非常有用。
2,@charset规则必须是样式表中第一个元素,前面不能有任何字符。用户代理必须忽略样式表开头之外的任何@chartset规则。
如果定义了几个@charset规则,则只使用第一个。
@import
允许用户从其他样式表导入样式规则。
@import url("https://fonts.googleapis.com/css?family=Libre+Baskerville");
@import url("print.css") print;
@import url("tv.css") projection, tv;
@import 'custom.css';
@import "common.css" screen, projection;
@import url('landscape.css') screen and
实际项目中不建议使用@import来引用其他CSS样式文件。这样不但请求多,还会造成堵塞。
@namespace
通常在处理多个命名空间的文档时有用,比如包含内联SVG或MathML的HTML,或者包含多个词汇表的XML。
@namespace url(http://www.w3.org/1999/xhtml);
@namespace svg url(http://www.w3.org/2000/svg);
/* 和所有XHTML中的a元素匹配,因为XHTML是默认的命名空间 /
a { color: red; }
/ 和所有SVG中的a元素匹配 /
svg|a { color: blue; }
/ 同时匹配XHTML和SVG中的a元素 */
*|a { color: orange; }
几点注意:
任何@namespace
规则都必须遵循所有@charset
和@import
规则,并位于样式表中所有其他@
规则和样式声明之前
@namespace
规则可以用于定义样式表的默认命名空间。定义默认命名空间时,所有通用选择器和类型选择器(不包含属性选择器)仅应用于该命名空间中的元素
@namespace
规则还可以用于定义命名空间的前缀。如果泛型、类型和属性选择器的前缀是命名空间的前缀,那么该选择器只在元素或属性的命名空间和名称匹配时才匹配
嵌套规则
与常规规则不同,后面会带一个{},括号会嵌套一些样式规则:
@[关键词] {
/* 样式规则 */
}
常见的嵌套规则:
@font-face
允许引用自定义字体。
@font-face { [ font-family: <family-name>; ] ||
[ src: [ <url> [ format(<string>#) ]? | <font-face-name> ]#; ] ||
[ unicode-range: <urange>#; ] ||
[ font-variant: <font-variant>; ] ||
[ font-feature-settings: normal | <feature-tag-value>#; ] ||
[ font-stretch: <font-stretch>; ] ||
[ font-weight: <weight>; ] ||
[ font-style: <style>; ]
}
一些注意事项:
- 作用域的限制。Web字体受到作用域的限制,因此
@font-face
规则中引用的字体资源必须与使用它们的页面位于相同的作用域,除非使用HTTP
访问控制来放宽这一限制 - 不考虑指定文件的
MIME
类型,因为没有为TrueType
、OpenType
和WOFF
字体定义MIME
类型 -
@font-face
不能在CSS选择器中声明
@keyframes
@keyframes
规则主要用来声明一个动画,在嵌套的规则中指定了动画各个节点(帧)的样式规则。
@keyframes <keyframes-name> {
<keyframe-block-list>
}
@keyframes
只是声明了一个动画,如果没有被animation-name
属性调用的话,那么该规则中的样式并不会起任何的作用。另外要使用关键帧列表有效,它必须包含动画开始和结束状态的规则,即0%
(from
)和100%
(to
)。如果没有指定这两个时间偏移量,那么@keyframes
声明就会无效,解析器将会忽略它,并且不能用于animation
中。
如果我们通过JavaScript来操作@keyframes
中的规则,可以使用CSSOM中的CSSKeyframesRule
。
特别注意:在
@keyframes
规则中声明的样式规则会覆盖元素中的样式规则,哪怕是带有!important
加强权重的样式规则。
@media
@media
规则是条件CSS中的一种,其条件是一个媒体查询。它由一个媒体查询列表(可以是空的)和一组规则组成。规则的条件是媒体查询的结果。
@media <media-query-list> {
<group-rule-body>
}
@supports
@supports
规则是条件CSS中的另一种,也是一条件组规则,其条件测试用户代理是否支持CSS属性/值对。它可以用于编写样式表,这些样式表在可用时使用新特性,但在不支持这些特性时将可以优雅地降级。
@supports <supports-condition> {
<group-rule-body>
}
@viewport
@viewport
规则事实上不是条件CSS中的一种。该规则在CSS中定义了一组嵌套的描述符,这些描述符主要用来控制移动设备上的viewport
设置。
@viewport {
<group-rule-body>
}
比如:
@viewport {
min-width: 640px;
max-width: 800px;
}
@page
@page
规则主要用于打印文档时候修改一些CSS属性。使用@page
我们只能改变部分CSS属性,例如间距属性margin
, 打印相关的orphans
, widows
, 以及page-break-*
, 其他CSS属性会被忽略。
@page <page-selector-list> {
<page-body>
}
@document
@document
规则指定应用于特定页面的样式的条件。该规则可以指定一个或多个匹配函数,如果其中任何一个函数应用于URL
,则该规则将对具有该URL
的文档生效。比如说,这个CSS文件被子站A
调用,和被子站C
调用,我们可以通过域名匹配来执行不同的CSS样式。这样,我们可以有效避免冲突,或者防止外链之类。
@document
/* 页面URL需要是 */
url(https://www.w3cplus.com/),
/* 页面URL的开头必须是... */
url-prefix(www.w3cplus.com/blog/),
/* 该域上的所有页面 */
domain(w3cplus.com),
/* 所有https协议页面 */
regexp("https:.*")
{
/* 开始样式 */
body {
color: #444;
}
}
@font-feature-values
@font-feature-values
规则主要用于给定字体家族的替代符号的索引定义命名值。它允许在font-variant-alternates
中使用一个公共名称来替换OpenType
中不可激活的特性,从而在使用多种字体时简化CSS。
@font-feature-values <family-name># {
<feature-value-block-list>
}
@counter-style
@counter-style
规则可以允许我们定义自定义的计数器的样式。计数器样式由@counter-style
规则中的描述符来指定,主要由system
、symbols
、additive-symbols
、negative
、prefiex
、suffix
和range
等组成。该规则的一般形式是:
@counter-style <counter-style-name> {
[ system: <counter-system>; ] ||
[ symbols: <counter-symbols>; ] ||
[ additive-symbols: <additive-symbols>; ] ||
[ negative: <negative-symbol>; ] ||
[ prefix: <prefix>; ] ||
[ suffix: <suffix>; ] ||
[ range: <range>; ] ||
[ pad: <padding>; ] ||
[ speak-as: <speak-as>; ] ||
[ fallback: <counter-style-name>; ]
}
具体使用的时候可以像下面这样:
@counter-style circled-alpha {
system: fixed;
symbols: Ⓐ Ⓑ Ⓒ;
suffix: " ";
}
li {
list-style: circled-alpha;
}
CSS的@
规则,其中@charset
、@import
、@font-face
、@keyframes
、@media
、@supports
是我们常见或已在项目中有见过的@
规则;而@namespace
、@viewport
、@page
、@document
、@font-feature-values
和@counter-style
等规则是我们不怎么常见。
在众多CSS的@
规则中,@media
、@supports
和@viewport
又被称为是条件CSS。
条件CSS之@media
响应式设计指的是,你的Web应用程序或Web页面应该从宽屏显示器到手机终端屏幕的所有东西上都显示得一样的好。
关键的就是条件CSS中的媒体查询,即@media
。媒体查询可以有条件的应用CSS规则,它告诉浏览器应该忽略或应用哪些CSS规则,而这些都取决于用户的设备终端。
整个媒体查询规则中主要包含了三个部分:媒体类型、媒体特性和逻辑操作符。
媒体查询类型
媒体查询类型简称为媒体类型,它是媒体查询条件中的重要部分之一。媒体类型允许你在不同的媒体类型上指定相应的样式文件。原始媒体类型集是在HTML4中定义的,主要用于<link>
元素上的媒体属性,比如screen
和print
等。
<link href="style.css" media="screen" />
<link href="print.css" media="print" />
创建媒体查询列表
在获取媒体查询结果之前,首先要创建MediaQueryList
对象,用来存储媒体查询。为了实现这个目的,需要使用window.matchMedia()
方法。
举个例子,比如你想设置一个查询列表用来判定设备屏幕处于横屏还是竖屏,那你可以像下面这样编码:
window.matchMedia("(orientation: portrait)");
当设备屏幕是横屏时,MediaQueryList
对象中的matches
属性返回的值为false
使用很简单,只需要给这个方法传一个mediaQueryString
参数,该参数是一个字符串,表示即将返回一个新MediaQueryList
对象的媒体查询。返回来的MediaQueryList
对象包含两个属性:
-
media
,是一个DOMString
类型,返回一个序列化的媒体查询列表 -
matches
,返回的是一个布尔值,匹配则为true
,否则为false
window.matchMedia("(min-width: 400px)")
// => MediaQueryList {media: "(min-width: 400px)", matches: true, onchange: null}
window.matchMedia("(min-width: 400px)").media
// => "(min-width: 400px)"
window.matchMedia("(min-width: 400px)").matches
// => true
借助新返回的MediaQueryList
对象的matches
属性
if (window.matchMedia("(min-width: 400px)").matches) { // 如果视窗宽度大于或等于400px,返回的值为true // 可以针对符合条件的情况下做一些想做的事情 } else { // 视窗小于400px的情况下,做一些自己想做的事情 }
接收和终止媒体查询的通知
let receiveMediaQueryMessage = window.matchMedia('(orientation: portrait)') receiveMediaQueryMessage.addListener(handleOrientationChange) function handleOrientationChange (receiveMediaQueryMessage) {
if (receiveMediaQueryMessage.matches) {
console.log('现在处在竖屏')
}
else
{
console.log('现在处在横屏')
}
}
handleOrientationChange(receiveMediaQueryMessage)
通过window.matchMedia()
方法创建了一个屏幕方向检测的查询列表receiveMediaQueryMessage
,并且添加了一个事件监听。需要注意的是,当我们添加监听之后,我们其实直接调用了一次监听。这会让我们的监听器以目前设备的屏幕方向来初始化判定代码。也就是说,如果我们代码中设定的设备处理竖屏模式,而实际上它在启动时处理横屏模式,那么我们在后面的判定就会出现矛盾。然后我们可以在handleOrientationChange()
函数中来查看媒体查询结果,并且可以设置屏幕方向变化后的逻辑处理代码。
使用addListener()
来接收媒体查询的通知,如果你不想再要接收媒体查询值变化的相关通知时,可以在MediaQueryList
上调用removeListener()
方法来移除监听,比如:
receiveMediaQueryMessage.removeListener(handleOrientationChange)