层叠样式表(Cascading Style Sheet,CSS)是一种指定HTML文档视觉表现的标准。
1. CSS概览
CSS忽略了“/*”和“*/”之间的注释,但是它不支持“//”后面的注释。
将一组定义视觉表现的CSS属性和对应的HTML元素关联在一起:
- 通过给每个单独的HTML元素设置style属性值的方式,称为内联样式
<p style="margin:20px;border:solid red 2px;">
- 通常将单独的HTML元素与CSS样式分开并把它们定义在一个样式表(stylesheet)中
- 用<style>和</style>标签把一个CSS样式表包起来放在<head>标签里,它就和HTML文档关联在一起了
- 当一个样式表需要在网站的多个页面中使用时,通常将其保存在自己的文件中
<head>
<title>Test Document</title>
<link rel="stylesheet" href="mystyles.css" type="text/css" />
</head>
一个选择器基于元素ID、类名或标签名或更多条件指定(或称“选择”)一个或多个文档中的元素。
样式表通过选择器将一组样式属性和使用选择器(selector)描述的一组HTML元素关联在一起。
CSS样式表的基本元素是样式规则,它们由选择器和包裹在一对“{}”中的CSS属性和值所组成。
.warning{ /*任何以"warning"类命名的元素*/
background-color:yellow; /*设置为黄色背景*/
border:solid black 5px; /*和黑色大边框*/
}
1.1 层叠
在CSS里"C"代表了“层叠”。该术语指示了应用于文档中任何给定元素的样式规则是各个“来源”的“层叠”效果
1.2 复合属性
某些经常在一起使用的样式属性可以组合起来使用一个特殊的复合属性。
- font-family、font-size和font-weight属性可以用font的复合属性值
font:bold italic 24pt helvetica;
- border、margin和padding属性就是为元素的每条边都设置边框、外边距和内边距(元素和边框之间的空间)的复合属性
1.3 CSS非标准属性
当浏览器厂商实现非标准CSS属性时,它们用将属性名前加了一个厂商前缀。Firefox使用-moz-,Chrome使用-webkit-,而IE使用-ms-
1.4 CSS 其它内容
- 利用CSS的@font-face规则可以下载并使用自定义字体
- CSS过渡。这是一个规范草案,它能自动将脚本化的CSS样式转换成平滑的动画过渡。
- CSS变换,它允许对任何元素应用任意的2D仿射变换(用一个矩阵表示旋转、缩放、转换或任意组合)
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
/*指定标题文本显示为蓝色、斜体*/
h1,
h2 {
color: blue;
font-style: italic;
} /*
*任何class="WARNING"的元素显示为大号、加黑文本,
*它有很宽的外边距、黄色背景和宽的红色边框
*/
.WARNING {
font-weight: bold;
font-size: 150%;
margin: 0 1in 0 1in; /*上右下左*/
background-color: yellow;
border: solid red 8px;
padding: 10px; /*4条边都是10像素*/
} /*
*class="WARNING"的元素里面的h1或h2标签内的文本,除了蓝色,还应该居中显示
*/
.WARNING h1,
.WARNING h2 {
text-align: center;
} /*id="special"的元素大写、居中显示*/
#special {
text-align: center;
text-transform: uppercase;
}
</style>
</head>
<body>
<h1>Cascading Style Sheets Demo</h1>
<div class="WARNING">
<h2>Warning</h2>
This is a warning! Notice how it grabs your attention with its bold text
and bright colors. Also notice that the heading is centered and in blue
italics.
</div>
<p id="special">
This paragraph is centered<br />
and appears in uppercase letters.<br />
<span style="text-transform:none">
Here we explicitly use an inline style to override the uppercase
letters.
</span>
</p>
</body>
</html>
2 CSS常用的样式属性
最重要的CSS特性是那些指定文档中每个元素的可见性、尺寸和精确定位的属性。其他CSS属性允许指定堆叠次序、透明度、裁剪区域、外边距、内边距、边框和颜色
2.1 CSS定位
CSS的position属性指定了应用到元素上的定位类型
- static,默认属性。指定元素按照常规的文档内容流(就是从左往右、从上到下)进行定位。静态定位的元素不能使用top、left和类似其他属性定位。
absolute该值指定元素是相对于它包含的元素进行定位。它的定位要么是相对于最近的定位祖先元素,要么是相对于文档本身。脱离了常规的文档内容流fixed该值指定元素是相对于浏览器窗口进行定位的。固定定位的元素总是显示在那里,不会随着文档其他部分而滚动。它不是文档流的一部分。relative相对于它在常规文档流中的位置进行调整定位。系统保留着元素在正常文档流中的空间,不会因为要填充空间而将其各边合拢,也不会将元素从新的位置“推开”。
一旦设置了元素的position属性为除了static以外的值,就可以通过元素的left、top、right和bottom属性指定元素位置
- 如果元素使用绝对定位,它的top和left属性应该解释为它是相对于其position属性设置为除static值以外的祖先元素。如果绝对定位的元素没有定位过的祖先,则它的top和left属性使用文档坐标进行度量——就是相对于文档左上角的偏移量。
- 如果你想相对于一个属于常规文档流中的容器绝对定位一个元素,则将容器的position指定为relative,top和left指定为0px。这就让容器变成了动态定位,但它仍留在文档流中原来的位置。(子绝对-父相对)
- 任何绝对定位元素的子元素都相对于容器进行定位。
CSS指定位置和大小属性是有单位的。定位和尺寸属性值以"px"结尾,代表像素。也可以使用英寸("in")、厘米("cm")、点("pt")和字体行高("em",一种当前字体行高的度量)。
<div style="position:absolute;left:25%;top:25%;width:50%;height:50%;
border:2px solid black" >
</div>
CSS也允许指定元素的位置和尺寸为其容器元素的百分比。
2.1.1 堆叠次序z-index
left、top、right和bottom属性是在容器元素中的二维坐标中指定X和Y坐标。z-index属性定义了第三个维度:它允许指定元素的堆叠次序,并指示两个或多个重叠元素中的哪一个应该绘制在其他的上面。
- z-index默认为0,可以是正或负的整数。当两个或多个元素重叠在一起时,它们是按照从低到高的z-index顺序绘制的。
- 如果重叠元素的z-index值一样,它们按照在文档中出现的顺序绘制,也即最后一个重叠的元素显示在最上面。
- 注意,z-index只对兄弟元素(例如,同一个容器的子元素)应用堆叠效果。
2.1.2 用CSS定位实现阴影效果
<!--text-shadow属性自动产生阴影效果-->
<span style="text-shadow:3px 3px 1px#888">Shadowed</span>
<!--这里我们利用定位可以产生相同的效果-->
<span style="position:relative;">
Shadowed<!--这里是投射阴影的文本-->
<span style="position:absolute;top:3px;left:3px;z-index:-1;color:#888">
Shadowed<!--这里是阴影-->
</span>
</span>
2.2 边框、外边距、内边距border margin padding
- 可以用单独的CSS属性指定边框的宽度、样式和颜色,也可以指定元素的每条边的边框。
border:solid black 1px;/*绘制一个1像素的黑色实线边框*/
border:3px dotted red;/*绘制一个3像素的红色点线边框*/
- 可以通过border-radius属性指定圆滑边框的所有角,也可以用更明确的属性名设置单独的圆角。
border-top-right-radius:50px;
margin和padding属性都指定元素周围的空白空间。主要的区别在于,margin指定边框外面——边框和相邻元素之间的空间; padding指定边框之内——边框和元素内容之间的空间。
外边距提供了常规文档流中(可能有边框的)元素和它的“邻居”之间的视觉空间。内边距保持元素内容和它的边框在视觉上分离。
可以用margin和padding属性直接为元素所有的4条边指定外边距和内边距。按照顺时针方式设置:上、右、下和左边的值。
padding: 1px 2px 3px 4px; /*以上代码等价于以下4行代码*/
padding-top: 1px;
padding-right: 2px;
padding-bottom: 3px;
padding-left: 4px;
2.3 CSS盒模型(box model)
上图显示了一个绝对定位的元素嵌套在一个定位的容器元素中。
注意外边距属性并没有图示:外边距margin与绝对定位的元素无关。
- width和height只指定了元素内容区域的尺寸,它不包含元素的内边距或边框(或外边距)所需的任何额外空间
- left和top属性指定了从容器边框内侧到定位元素边框外侧的距离。这些属性不是从容器内容区域的左上角开始度量的,而是从容器内边距的左上角开始的。
边框盒模型和box-sizing属性
- 标准CSS盒模型规定width和height样式属性给定内容区域的尺寸,并且不包含内边距和边框。可以称此盒模型为“内容盒模型”。
- CSS3引进了box-sizing属性,默认值是content-box,它指定了上面描述的标准的盒模型。如果替换为box-sizing:border-box,width和height属性将包含边框和内边距。
<div style="box-sizing:border-box;width:50%;
padding:10px;border:solid black 2px;">
支持使用calc()计算CSS的值
// calc()的-号左右必须加空格calc才生效
<div style="width:calc(50% - 12px);padding:10px;border:solid black 2px;">
2.4 visibility display 元素显示和可见性
- visibility属性:当其值设置为hidden时,该元素不显示;当其值设置为visible时,该元素显示。
- display属性更加通用,它用来为接收它的容器指定元素的显示类型。它指定元素是否是块状元素、内联元素、列表项等。但是,如果display设置为none,受影响的元素将不显示,甚至根本没有布局。
- 对于一个常规布局流中的元素,设置visibility属性为hidden使得元素不可见,但是在文档布局中仍保留了它的空间。类似的元素可以重复隐藏和显示而不改变文档布局。
- 但是,如果元素的display属性设置为none,在文档布局中不再给它分配空间,它各边的元素会合拢,就当它从来不存在。
2.5 颜色、透明度
- 可以用background-color属性指定任何元素的背景颜色
- 在CSS中更一般的指定颜色的语法是使用十六进制数分别指定组成颜色的红、绿和蓝色分量,每个分量可以使用一位或两位数字。
- RGBA色彩空间(红、绿、蓝色值加上指定颜色透明度的alpha值)中的颜色
- HSL(色相-饱和度-值)和HSLA颜色
- background-image属性指定使用的图像,background-attachment、background-position和background-repeat属性
- 如果没有为元素指定背景颜色或图像,它的背景通常透明,可以将其显式设置为"transparent"
opacity:.75;/*透明度,CSS3标准属性*/
filter:alpha(opacity=75);/*IE透明度,注意没有小数点*/
CSS3的opacity属性,该属性值是0~1之间的数字,1代表100%不透明(默认值),而0代表0%不透明(或100%透明)。
2.6 部分可见 overflow clip
visibility属性可以让文档元素完全隐藏,而overflow和clip属性允许只显示元素的一部分。
overflow属性指定内容超出元素的大小(例如,用width和height样式属性指定)时该如何显示:
- visible,默认值。如果需要,内容可以溢出并绘制在元素的边框的外面。
- hidden,裁剪掉和隐藏溢出的内容,即在元素尺寸和定位属性值定义的区域外不会绘制内容。
- scroll,元素一直显示水平和垂直滚动条。如果内容超出元素尺寸,允许用户通过滚动来查看额外的内容。此属性值负责文档在计算机屏幕中的显示,例如,打印纸质文档时滚动条是没有意义的。
- auto 滚动条只在内容超出元素尺寸时显示,而非一直显示。 clip属性确切地指定了应该显示元素的哪个部分,它不管元素是否溢出。clip属性的值指定了元素的裁剪区 域。
// 要只显示元素的100×100像素大小部分,可以赋予该元素style属性:
style="clip:rect(0px 100px 100px 0px);"
2.7 重叠半透明窗口
<!DOCTYPE html>
<head>
<style type="text/css">
div.window {
/*指定窗口的尺寸和边框*/
position: absolute; /*position在其他地方指定*/
width: 300px;
height: 200px; /*窗口尺寸,不含边框*/
border: 3px outset gray; /*注意3D"outset"边框效果*/
}
div.titlebar {
/*指定标题栏的定位、尺寸和样式*/
position: absolute; /*它是定位元素*/
top: 0px;
height: 18px; /*标题栏18px+内边距和边框*/
width: 290px; /*290+5px左、右内边距=300*/
background-color: #aaa; /*标题栏颜色*/
border-bottom: groove gray 2px; /*标题栏只有底部边框*/
padding: 3px 5px 2px 5px; /*顺时针值:top、right、bottom、left*/
font: bold 11pt sans-serif; /*标题栏字体*/
}
div.content {
/*指定窗口内容的尺寸、定位和滚动*/
position: absolute; /*它是定位元素*/
top: 25px; /*18px标题+2px边框+3px+2px内边距*/
height: 165px; /*200px总共-25px标题栏-10px内边距*/
width: 290px; /*300px宽度-10px内边距*/
padding: 5px; /*4条边上都有空间*/
overflow: auto; /*如果需要显示滚动条*/
background-color: #fff; /*默认白色背景*/
}
div.translucent {
/*此类让窗口部分透明*/
opacity: 0.75; /*透明度标准样式*/
filter: alpha(opacity=75); /*IE的透明度*/
}
</style>
</head>
<body>
<!--定义一个窗口:"window"div有一个标题栏和-->
<!--其内是一个内容div。注意,如何设置定位-->
<!--一个扩充了样式表的style属性-->
<div class="window" style="left:10px;top:10px;z-index:10;">
<div class="titlebar">Test Window</div>
<div class="content">
1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />0<br /><!--若干行-->
1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />0<br /><!--展示滚动-->
</div>
</div>
<!--定义另一个窗口:用不同的定位、颜色和字体重量-->
<div class="window" style="left:75px;top:110px;z-index:20;">
<div class="titlebar">Another Window</div>
<div
class="content translucent"
style="background-color:#ccc;font-weight:bold;"
>
This is another window.Its<tt>z-index</tt>puts it on top of the other one.
CSS styles make its content area translucent,in browsers that support
that.
</div>
</div>
</body>
3 Js脚本化HTML内联样式
脚本化CSS最直截了当的方法就是更改单独的文档元素的style属性。
类似大多数HTML属性,style也是元素对象的属性,它可以在JavaScript中操作。但是style属性不同寻常:它的值不是字符串,而是一个CSSStyleDeclaration对象。
名字约定:JavaScript中的CSS属性
- 很多CSS样式属性(如font-size)在名字中包含连字符。在JavaScript中,连字符是减号,CSSStyleDeclaration属性名的格式应该是移除连字符,将每个连字符后面紧接着的字母大写。
e.style.font-size="24pt";//语法错误!
e.style.fontFamily="sans-serif";
- 当一个CSS属性(如float属性)在JavaScript中对应的名字是保留字时,在之前加"css"前缀来创建合法的CSSStyleDeclaration名字。例如cssFloat属性是设置或查询元素的CSS float属性
- 使用CSSStyleDeclaration对象的style属性时,记住所有样式的值都应该是字符串
e.style.position="absolute";
e.style.backgroundColor="#ffffff";
- 记住所有的定位属性都需要包含单位。
e.style.left=300;//错误:它是数字而不是字符串
e.style.left="300";//错误:缺少单位
e.style.left="300px";
- 独立设置4个margin属性值更加便捷
e.style.marginTop=topMargin+"px";
e.style.marginRight=rightMargin+"px";
e.style.marginBottom=bottomMargin+"px";
e.style.marginLeft=leftMargin+"px";
HTML元素的style属性是它的内联样式,它覆盖在样式表中的任何样式说明
元素的内联样式只在设置样式的时候有用,如果需要查询元素的样式,就要使用计算样式
可以使用元素的getAttribute()和setAttribute()方法或CSSStyleDeclaration对象的cssText属性来实现
//两者都可设置e的样式属性为字符串s
e.setAttribute("style",s);
e.style.cssText=s;//两者都可查询元素的内联样式
s=e.getAttribute("style");
s=e.style.cssText;
CSS动画
使用setTimeout()或setInterval()重复调用函数来修改元素的内联样式达到产生视觉动画效果的目的。
shake()将元素从一边到另一边快速移动或“震动”,例如,当输入无效的数据时,它吸引用户的注意力。fadeOut()通过指定的时间(默认是500毫秒)降低元素的不透明度,使得元素淡出和消失。
<script>
//将e转化为相对定位的元素,使之左右"震动"
//第一个参数可以是元素对象或者元素的id
//如果第二个参数是函数,以e为参数,它将在动画结束时调用
//第三个参数指定e震动的距离,默认是5像素
//第四个参数指定震动多久,默认是500毫秒
function shake(e, oncomplete, distance, time) {
//句柄参数
if (typeof e === "string") e = document.getElementById(e);
if (!time) time = 500;
if (!distance) distance = 5;
var originalStyle = e.style.cssText; //保存e的原始style
e.style.position = "relative"; //使e相对定位
var start = new Date().getTime(); //注意,动画的开始时间
animate(); //动画开始
//函数检查消耗的时间,并更新e的位置
//如果动画完成,它将e还原为原始状态
//否则,它更新e的位置,安排它自身重新运行
function animate() {
var now = new Date().getTime(); //得到当前时间
var elapsed = now - start; //从开始以来消耗了多长时间?
var fraction = elapsed / time; //是总时间的几分之几?
if (fraction < 1) {
//如果动画未完成
//作为动画完成比例的函数,计算e的x位置
//使用正弦函数将完成比例乘以4pi
//所以,它来回往复两次
var x = distance * Math.sin(fraction * 4 * Math.PI);
e.style.left = x + "px"; //在25毫秒后或在总时间的最后尝试再次运行函数
//目的是为了产生每秒40帧的动画
setTimeout(animate, Math.min(25, time - elapsed));
} else {
//否则,动画完成
e.style.cssText = originalStyle; //恢复原始样式
if (oncomplete) oncomplete(e); //调用完成后的回调函数
}
}
}
//以毫秒级的时间将e从完全不透明淡出到完全透明
//在调用函数时假设e是完全不透明的
//oncomplete是一个可选的函数,以e为参数,它将在动画结束时调用
//如果不指定time,默认为500毫秒
//该函数在IE中不能正常工作,但也可以修改得能工作,
//除了opacity,IE使用非标准的filter属性
function fadeOut(e, oncomplete, time) {
if (typeof e === "string") e = document.getElementById(e);
if (!time) time = 500; //使用Math.sqrt作为一个简单的“缓动函数”来创建动画
//精巧的非线性:一开始淡出得比较快,然后缓慢了一些
var ease = Math.sqrt;
var start = new Date().getTime(); //注意:动画开始的时间
animate(); //动画开始
function animate() {
var elapsed = new Date().getTime() - start; //消耗的时间
var fraction = elapsed / time; //总时间的几分之几?
if (fraction < 1) {
//如果动画未完成
var opacity = 1 - ease(fraction); //计算元素的不透明度
e.style.opacity = String(opacity); //设置在e上
setTimeout(
animate, //调度下一帧
Math.min(25, time - elapsed)
);
} else {
//否则,动画完成
e.style.opacity = "0"; //使e完全透明
if (oncomplete) oncomplete(e); //调用完成后的回调函数
}
}
}
</script>
<script>
shake("mydiv",e => { console.log(e.style.cssText);}, 3000 );
</script>
4. 查询计算出的样式getComputedStyle()
用浏览器窗口对象的getComputedStyle()方法来获得一个元素的计算样式。此方法的第一个参数就是要获取其计算样式的元素,第二个参数也是必需的,通常是null或空字符串,但它也可以是命名CSS伪对象的字符串,如":before"、":after"、":first-line"或":first-letter"。返回值是一个CSSStyleDeclaration对象
类似内联样式,计算样式也是用一个CSSStyleDeclaration对象来表示的,区别是,计算样式是只读的,不能设置这些样式
- 计算样式的值是绝对值:类似百分比和点之类相对的单位将全部转换为绝对值。
- 不计算复合属性,它们只基于最基础的属性。例如,不要查询margin属性,应该使用marginLeft和marginTop等
5 Js脚本化HTML的class属性值
如下代码设置和清除元素的className属性来为元素添加和移除"attention"类:
function grabAttention(e){e.className="attention";}
function releaseAttention(e){e.className="";}
如果有多个类名className属性就无法工作了。如果元素已经有一个类了,为该元素调用grabAttention()函数将覆盖已存在的类。
HTML5解决了这个问题,为每个元素定义了classList属性。该属性值是DOMTokenList对象:一个只读的类数组对象:
- add()和remove()从元素的class属性中添加和清除一个类名。
- toggle()表示如果不存在类名就添加一个;否则,删除它。
- 最后,contains()方法检测class属性中是否包含一个指定的类名。
6. 脚本化样式表
在脚本化样式表时,将会碰到两类需要使用的对象。
- 第一类是元素对象,由<style>和<link>元素表示,两种元素包含或引用样式表。
- 第二类是CSSStyleSheet对象,它表示样式表本身。document.styleSheets属性是一个只读的类数组对象,它包含CSSStyleSheet对象,表示与文档关联在一起的样式表
6.1 开启、关闭样式表
<style>、<link>元素和CSSStyleSheet对象都定义了一个在JavaScript中可以设置和查询的disabled属性。顾名思义,如果disabled属性为true,样式表就被浏览器关闭并忽略。
6.2 查询、删除、插入样式表规则
除了样式表的开启和关闭以外,CSSStyleSheet对象也定义了用来查询、插入和删除样式表规则的API
- document.styleSheets[]数组的元素是CSSStyleSheet对象。CSSStyleSheet对象有一个cssRules[]数组,它包含样式表的所有规则
- cssRules[]或rules[]数组的元素为CSSRule对象。在标准API中,CSSRule对象代表所有CSS规则,包含如@import和@page等指令。
CSSRule对象有两个属性
- selectText是规则的CSS选择器,它引用一个描述与选择器相关联的样式的可写CSSStyleDeclaration对象
- cssText属性来获得规则的文本表示形式。
标准的API接口定义了insertRule()和deleteRule()方法来添加和删除规则
6.3 创建样式表
创建整个新样式表并将其添加到文档是中可能的。只要创建一个全新的<style>元素,将其插入到文档的头部,然后用其innerHTML属性来设置样式表内容。
function addStyles(styles) {
//首先,创建一个新样式表
var styleElt, styleSheet;
var head = document.getElementsByTagName("head")[0];
styleElt = document.createElement("style"); //新的<style>元素
head.appendChild(styleElt); //把它插入<head>中
//现在,新的样式表应该是最后一个
styleSheet = document.styleSheets[document.styleSheets.length - 1];
//现在向其中插入样式
if (typeof styles === "string") {
//参数是样式表文本
if (styleElt) styleElt.innerHTML = styles;
} else {
//参数是待插入的单独的规则的对象
var i = 0;
for (selector in styles) {
if (styleSheet.insertRule) {
var rule = selector + "{" + styles[selector] + "}";
styleSheet.insertRule(rule, i++);
} else {
styleSheet.addRule(selector, styles[selector], i++);
}
}
}
}