CSS(Cascading Style Sheet)层叠级联样式表

CSS3 概述

  • CSS3 在 CSS2 版本的基础上,新增了很多特性,例如边框圆角、动画效果。
  • 在 CSS2 的时代,实现圆角必须要用图片才能实现,而 CSS3 只要一行样式就能实现圆角。
  • 在 CSS3 的时代,动画效果一定要使用 JavaScript 配合复杂的 CSS 样式操作才能实现(或者用 jQuery 这种第三方库)。CSS3 同样可以简单地实现动画效果,而且效果更佳。
  • 早些年头,因为浏览器的兼容问题,并未广泛引用,但是近几年,随着随着各大浏览器厂商的标准化,大家可以畅快第使用 CSS3 了

CSS3 新特性

  1. 边框圆角
  2. 阴影
  3. 形变:旋转、缩放、位移
  4. 过渡效果
  5. 动画效果
  6. 媒体查询
  7. flex 布局
  8. grid 布局

等等(选择器、字体)......

CSS的三种导入方式

行内(内联)样式

<!--内联样式权重高于嵌入样式,不建议使用,用得越多就越难维护-->
<h1 style="color: yellow">标题</h1>

嵌入样式

<style>
    h1{
        color: red;
    }
</style>

外部样式(推荐)

  • HTML文件中使用link标签引入外部样式(链接式)
<link rel="stylesheet" href="CSS/style.css">
  • HTML文件中在style标签内使用@import(导入式)
<style>
    /*CSS 2.1所特有的写法,不推荐使用*/
    @import url("我的第一个CSS程序/CSS/style.css");
</style>
  • CSS文件
/*CSS注释*/
h1{
    color: blue;
}

三种方式的优先级

  • 行内样式最优先
  • 内部样式和外部样式谁后执行谁生效

选择器

基本选择器

id选择器

#id-name{
    
}

标签选择器

/*选择P标签*/
p{
    
}

类选择器

.class-name{
    
}
<!--一个标签可以加多个class-->
<h1 class="class1 class2">
    hello
</h1>

通配符选择器

*{
    
}

选择器优先级

相同选择器:后面的覆盖前面的
不同选择器:id选择器(100)>class选择器(10)>标签选择器(1)
层级选择器:按权重累加计算
<style>
    /*100+10=110*/
    .box #txt{
        color:red;
	}
    /*100+1=101*/
    #box2 h1{
        color:blue;
        /*color:blue !important;
        这样写可以设置最高权重
        */
    }
</style>
<div class="box" id="box2">
    <h1 class="title title2" id="txt">
        hello
    </h1>
</div>

层级选择器

后代选择器

/*选中body标签下的所有P标签*/
body p{
    
}

子代选择器

/*只选中直属于body标签的P标签,不包括body中其他标签下的*/
body>p{
    
}

相邻兄弟选择器

/*只选中属于class类的P标签的下一个P标签*/
.class+p{
    
}

通用选择器

/*选中所有属于class类的P标签向下的所有P标签*/
.class~p{
    
}

组合选择器

h1,h2{
    
}

结构伪类选择器(条件)

/*选中ul的第一个子元素*/
ul li:first-child{
    
}
/*选中ul的最后一个子元素*/
ul li:last-child{
    
}
/*从当前p元素的父级元素下选择第2个元素,第2个元素是P才生效*/
p:nth-child(2){
    
}
/*从当前p元素的父级元素下选择第1个p元素*/
p:nth-of-type(1){
    
}
/*鼠标移动到a标签上时对a标签生效*/
a:hover{
    
}
/*鼠标移动到a标签上时对p标签生效*/
a:hover > p{
    
}

伪元素选择器(增加元素)

/*
CSS2:伪类选择器和伪元素选择器都是一个冒号
CSS3:让伪元素选择器增加一个冒号
目前浏览器两者都支持
*/
h1::before{
    content:"在h1前面"
}
h1::after{
    content:"在h1后面"
}

/*可以起到装饰作用*/
.classname::before,.classname::before{
	content:"-----"
}

属性选择器

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .main a{
            float: left;
            color: #bd200d;
            background: blue;
            display: block;
            text-align: center;
            height: 50px;
            width: 50px;
            border-radius: 50px;
            font: bold 20px/50px Arial;
            margin-right: 10px;
            text-decoration: none;
        }
        /*属性选择器
        语法:a[]{}
        []中可以写属性名、属性名=属性值
        = 绝对相等
        *= 包含
        ^= 以这个开头
        $= 以这个结尾
        ……
        */
        /*存在id属性的元素*/
        a[id]{
            color: black;
        }
        /*id为特定值的元素*/
        a[id="id1"]{
            color: aqua;
        }
        /*id中存在2的元素*/
        a[id*="2"]{
            color: yellow;
        }
        /*class中存在b的元素*/
        a[class*="b"]{
            background: gray;
        }
        /*href中以http开头的元素*/
        a[href^="http"]{
            width: 100px;
        }
        /*href中以ppt结尾的元素*/
        a[href$="ppt"]{
            height: 100px;
        }
        /*a类中有id的元素*/
        .a[id]{
            width: 200px;
        }
    </style>
</head>
<body class="main">
<a href="https://www.baidu.com" class="a b c" id="id1">1</a>
<a href="https://www.jd.com">2</a>
<a href="https://www.taobao.com">3</a>
<a href="image/a.png" class="a" id="id2">4</a>
<a href="image/b.jpg" class="b" id="id3">5</a>
<a href="video/c.mp4" class="c">6</a>
<a href="audio/d.mp3">7</a>
<a href="file/e.ppt" class="a c">8</a>
<a href="file/f.docx" class="b c">9</a>
<a href="file/g.xls" class="a b">10</a>
</body>
</html>

美化网页元素

字体样式

<!--
font-family: 字体(中英文字体用,隔开);
font-size: 字体大小(单位px,em……);chrom浏览器最小值为12px
font-weight: 字体粗细(bold 粗体,也可以用数字);
color: 字体颜色;
line-height: 行高;
font-style: 字体风格(oblique 斜体);
-->
<style>
    body{
        font: oblique bold 20px/50px "楷体";
    }
    a{
        font-family: "Times New Roman" ,楷体;
        font-size: 50px;
        font-weight: bold;
        color: red;
        line-height: 50px;
        font-style: oblique;
    }
</style>

文本样式

<!--
color颜色:
1.单词(red,green,blue...)
2.RGB(color:rgb(0,255,0))
3.RGBA(color:rgba(0,0,255,0.1))
R:红(0~255)
G:绿(0~255)
B:蓝(0~255)
A:透明度(0~1)

排版水平居中 text-align: center;
首行缩进2字符 text-indent: 2em;

行高和块的高度一致时就可以上下居中:
height: 200px;
line-height: 200px;

下划线 text-decoration: underline;
中划线 text-decoration: line-through;
上划线 text-decoration: overline;
去划线 text-decoration: none;
垂直居中 vertical-align: middle;
-->
<style>
    h1{
        color: rgba(0,255,0,20%);
        text-align: center;
    }
    p{
        text-indent: 2em;
        height: 200px;
        line-height: 200px;
        text-decoration: underline;
    }
    /*去超链接的下划线*/
    a{
        text-decoration: none;
    }
    /*多标签选择器*/
    img,span{
        /*垂直居中排列*/
        vertical-align: middle;
    }
</style>

<p>
    <img src="../Resources/image/Cover.jpg">
    <span>文字</span>
</p>

超链接伪类

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        /*初始状态*/
        a{
            color: black;
            text-decoration: none;
        }
        /*鼠标悬停状态*/
        a:hover{
            color: orange;
        }
        /*鼠标按住未释放的状态*/
        a:active{
            color: blue;
        }
        /*以上三个可以同时存在,都能生效*/
        /*链接被访问过的状态*/
        a:visited{
            color: gray;
        }
        /*链接未被访问过的状态*/
        a:link{
            color: red;
        }
        /*visited和link优先级最高,只要有一个生效,其他的就不生效了*/
    </style>
</head>
<body>
<a href="https://www.baidu.com????" target="_blank">百度</a>
</body>
</html>

文字阴影(text-shadow)

<style>
    p{
        color: gray;
        /*text-shadow: 阴影颜色 水平偏移(允许负值) 垂直偏移(允许负值) 模糊距离*/
        text-shadow: #bd200d 5px 5px 2px;
    }
</style>
<p>Hello word!</p>

列表样式(list-style)

  • none:去掉圆点
  • circle:空心圆
  • square:方块
  • decimal:数字
  • inside:列表样式在边距之内
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        #nav{
            background: gray;
            width: 180px;
            height: 140px;
        }
        .title{
            color: black;
            font-size: 15px;
            font-weight: bold;
            height: 30px;
            line-height: 30px;
            background: red;
            text-indent: 1em;
            margin-bottom: -10px;
        }
        ul li{
            height: 20px;
            list-style: none;
        }
        a{
            color: #090909;
            font-size: 10px;
            text-decoration: none;
        }
        a:hover{
            color: orange;
            text-decoration: underline;
        }
    </style>
</head>
<body>
<div id="nav">
    <h2 class="title">全部商品分类</h2>
    <ul>
        <li><a href="#">图书</a>&nbsp;&nbsp;&nbsp;<a href="#">居家</a></li>
        <li><a href="#">电器</a>&nbsp;&nbsp;&nbsp;<a href="#">服装</a></li>
        <li><a href="#">数码</a>&nbsp;&nbsp;&nbsp;<a href="#">办公</a></li>
        <li><a href="#">彩票</a>&nbsp;&nbsp;&nbsp;<a href="#">食品</a></li>
    </ul>
</div>
</body>
</html>

背景

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        body{
            /*渐变色*/
            background-color: #4158D0;
            background-image: linear-gradient(13deg, #4158D0 0%, #C850C0 46%, #FFCC70 100%);
        }
        div{
            height: 1000px;
            width: 1000px;
            /*border:边框宽度,边框样式(solid实线),边框颜色*/
            border: 1px solid red;
            background-image: url("../../Resources/image/kl.jpg");
            /*默认是平铺的*/
            background-repeat: repeat;
        }
        #div1{
            /*横向平铺*/
            background-repeat: repeat-x;
        }
        #div2{
            /*纵向平铺*/
            background-repeat: repeat-y;
        }
        #div3{
            /*不平铺*/
            background-repeat: no-repeat;
            background-position: 100px 200px;
        }
    </style>
</head>
<body>
<div id="div1"></div>
<div id="div2"></div>
<div id="div3"></div>
<div id="div4"></div>
</body>
</html>

盒子模型

盒子模型

margin:外边距:top\right\bottom\left padding内边距:top\right\bottom\left border:边框:width\style\color(border属性简写的三个值是没有顺序要求的)

border-style:

描述
none 定义无边框
dotted 定义点状边框
dashed 定义虚线
solid 定义实线
double 定义双线

元素宽高计算

  • 默认情况下

元素的实际宽度 = border-left + border-right + width + padding-left + padding-right;

元素的实际高度 = border-top + border-bottom + width + padding-top + padding-bottom;

  • 设置box-sizing:border-box;(很方便的属性)

image-20220317163235716

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        
        /*元素边距初始化*/
        *{
            margin: 0;
            padding:0;
            box-sizing:border-box;
        }
        
        #login{
            border: 1px solid gray;
            
            /*auto自动对齐实现元素水平居中*/
            margin: 0 auto;
            padding: 0;
            width: 300px;
        }
        #login div:nth-of-type(1) input{
            /*border:粗细 样式(solid:实线,dashed:虚线) 颜色*/
            border: 3px solid black;
        }
        #login div:nth-of-type(2) input{
            border: 3px dashed red;
        }
        form{
            background-color: orange;
        }
        input[type=submit]{
            color: #bd200d;
            background-color: #C850C0;
        }
        input[type=submit]:hover{
            color: #4158D0;
        }
        #app>div>img{
            width: 100px;
            height: 100px;
            /*设置边框圆角*/
            border-radius: 50px;
            /*居中*/
            display: block;/*把img从内联元素变为块元素*/
            margin: 0 auto;
            /*设置边框阴影*/
            /* 颜色 水平偏移 垂直偏移 模糊距离*/
            box-shadow: #bd200d 0px 0px 20px;
        }
    </style>
</head>
<body>
<div id="app">
    <div>
        <img src="../../Resources/image/kl.jpg">
    </div>
    <div id="login">
        <h2>会员登录</h2>
        <form action="#">
            <div id="username">
                <span>用户名:</span>
                <input type="text">
            </div>
            <div>
                <span>密码:</span>
                <input type="password">
            </div>
            <div>
                <input type="submit" value="登录">
            </div>
        </form>
    </div>

</div>
</body>
</html>

浮动

  • 块元素:可以设置宽度和高度,独占一行
<h1></h1>	<p></p>	<div></div>	<ul></ul>	<li></li>
  • 行内/内联元素:不可以设置宽度和高度,不独占一行
<span></span>	<a></a>	<strong></strong>
  • 行内块元素:可以设置宽度和高度,不独立成行
<img>	<input>	<button></button>

display属性(改变元素的分类)

  • block:转换为块元素
  • inline:转换为行内元素
  • inline:block:转换为行内块元素
  • none:隐藏元素

两个div在同一行显示

将元素设置为浮动元素(float),块元素可以在同一行显示,脱离文档流

==float属性的值:none\left\right==

行内元素可以被包含在块元素中,反之不可以


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>

        div{
            width: 100px;
            height: 100px;
            border:2px solid red;
            display: inline-block;
            float: right;
        }
        span{
            width: 100px;
            height: 100px;
            border:2px solid red;
            display:inline-block;
            /*浮动*/
            float: right;
            /*
            clear:何处不允许有浮动元素
            both:左右两侧
            right:右侧
            left:左侧
            */
            clear: both;
        }
        h1{
            display: none;
        }
    </style>
</head>
<body>
    <div>div块元素</div>
    <span>span行内元素</span>
    <h1>消失不见</h1>
</body>
</html>

父级边框塌陷问题解决方案(清除浮动造成的不良影响)

  • 增加父级元素的高度
#father{
    height: 100px;
}
  • 增加一个空的div标签
<style>
    .clear{
        clear: both;
        margin: 0;
        padding: 0;
    }
</style>

<div id="father">
<!--在父级元素内部最下面-->
    <div class="clear"></div>
</div>
  • 在父级元素中加一个overflow
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        #father{
            border: 1px solid red;
            overflow: hidden;
        }
        #father div img{
            float: right;
        }
    </style>
</head>
<body>

<div id="father">
    <div>
        <img src="../../Resources/image/aimiliya.webp">
    </div>
    <div>
        <img src="../../Resources/image/kl.jpg">
    </div>
</div>

</body>
</html>
  • ==在父类中加伪元素(推荐)==
.clear::before,.clear::after{
            content: "";
            display: block;
            clear:both;
        }

例如:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>index</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        .clear::before,.clear::after{
            content: "";
            display: block;
            clear:both;
        }
        .aside{
            width: 50px;
            height: 50px;
            border:1px solid red;
            float:left;
            box-sizing: border-box;
        }
        .content{
            width: 50px;
            height: 50px;
            border:1px solid red;
            float:left;
            box-sizing: border-box;
        }
        .box{
            background-color:blue;
            width: 300px;
            height: 300px;
        }
    </style>
</head>
<body>
<div class="container clear">
    <div class="content">
        内容
    </div>
    <div class="aside">
        边栏
    </div>
</div>
<div class="box">
</div>
</body>
</html>

定位(position)

默认取值为static

相对定位(relative)

对象遵循常规流,并且参照自身在常规流中的位置通过top,right,bottom,left这4个定位偏移属性进行偏移时不会影响常规流中的任何元素。特异性——移动元素后,元素本来占有的位置会保留,然后会相对原来的位置定位。如图: image-20220317173725573

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        body>div{
            display: block;
            margin: 0 auto;
            padding: 4px;
            border: 2px solid red;
            width: 300px;
            height: 300px;
        }
        a{
            color: white;
            text-align: center;
            line-height: 100px;
            text-decoration: none;
            background-color: pink;
            display: block;
            width: 100px;
            height: 100px;
        }
        a:hover{
            background-color: blue;
        }
        body>div>div:nth-of-type(2){
            position: relative;
            top: -100px;
            right: -200px;
        }
        body>div>div:nth-of-type(4){
            position: relative;
            top: -100px;
            right: -200px;
        }
        body>div>div:nth-of-type(5){
            position: relative;
            top: -300px;
            right: -100px;
        }
    </style>
</head>
<body>
<div>
    <div><a href="?">链接1</a></div>
    <div><a href="?">链接2</a></div>
    <div><a href="?">链接3</a></div>
    <div><a href="?">链接4</a></div>
    <div><a href="?">链接5</a></div>
</div>
</body>
</html>

绝对定位

对象脱离常规流,此时偏移属性参照的是离自身最近的定位祖先元素,如果没有**已定位的(非static)**祖先元素,则一直回溯到body元素。盒子的偏移位置不影响常规流中的任何元素,其margin不与其他任何margin折叠。通常可以把父级元素设置为relative来改变默认的body元素。如图: image-20220317173929420

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        body{
            border: 2px solid red;
            height: 2000px;
        }
        body>div{
            display: block;
            margin: 0 auto;
            padding: 4px;
            border: 2px solid red;
            width: 300px;
            height: 2000px;
        }
        a{
            color: white;
            text-align: center;
            line-height: 100px;
            text-decoration: none;
            background-color: pink;
            display: block;
            width: 100px;
            height: 100px;
        }
        a:hover{
            background-color: blue;
        }
        body>div>div:nth-of-type(2){
            position: sticky;
            top: 300px;
            right: -100px;
            /*设置不透明度*/
            opacity: 0.2;
        }
        body>div>div:nth-of-type(4){
            position: absolute;
            top: 0px;
            right: 0px;
        }
        body>div>div:nth-of-type(5){
            position: fixed;
            bottom: 0px;
            right: 0px;
        }
    </style>
</head>
<body>
<div>
    <div><a href="?">1</a></div>
    <div><a href="?">sticky</a></div>
    <div><a href="?">3</a></div>
    <div><a href="?">absolute</a></div>
    <div><a href="?">fixed</a></div>
</div>
</body>
</html>

固定定位(fixed)

脱离文档流,默认参照物为浏览器视窗位置

常用于返回顶部等常驻页面的元素。

z-index

用整数值来定义堆叠级别。可以为负值。 数值大的在前方显示。

CSS3新特性

边框圆角

  • border-radius:左上 右上 右下 左下

  • 如果设置两个值,第一个值表示左上和右下,第二个值表示右上和左下。

    border: 1px solid red;
    
  • 四个角是一样的

    border-radius: 50px;
    
  • 左上 右上 右下 左下

    border-radius: 10px 20px 30px 40px;
    
  • 左上右下 右上左下

    border-radius: 20px 40px;
    
  • 高度宽度相同时,边框圆角设成 50%才能设成正圆。

    border-radius: 50%;
    

阴影

  • box-shadow: 10px 20px 30px blue;

    参数分别表示:x 轴偏移量,y 轴偏移量,模糊半径,阴影颜色(不设置颜色为黑色)

    box-shadow: 10px 20px 30px;
    

    蓝色阴影

    box-shadow: 10px 20px 30px blue;
    

    x 轴偏移量为 100px;

    box-shadow: 100px 20px 30px blue;
    

    y 轴偏移量为 200px;

    box-shadow: 10px 200px 30px blue;
    

    模糊半径,越大越模糊

    box-shadow: 10px 20px 50px blue;
    

形变transform

  • rotate();旋转 deg 单位表示角度

    /*顺时针旋转 45° 单位是 deg 角度*/
    transform: rotate(45deg);
    
  • scale();缩放

    /*缩放 0.5 倍*/
    transform: scale(0.5);
    
  • translate();位移

    /*位移 可以设百分数% 具体值单位是 px 横坐标向右位移 50px 纵坐标向下位移 100px*/
    transform: translate(50px, 100px);
    
  • transform 都是同一个属性,分开写会被覆盖,所以多个形变要加空格

    transform: rotate(45deg) translate(50px, 100px);
    

过渡效果transition

通过transition属性,可以设置元素的过渡效果,

==当某个属性被设置成过渡属性后,属性的值如果发生变化,就会以动画的形式从初始状态过渡到结束状态==

  • transition-property 过渡属性(例如 transform)

  • transition-duration 过渡持续时间(例如 1s)

  • transition-timing-function 过渡函数

  • transition-delay 过渡延迟时间

简写:transition: 属性 秒数 函数 延迟;

/* transition-property: transform; */
/* transition-duration:1s; */
transition: transform 1s ease 1s;
/* transition-property: transform; */
/* transition-duration:1s; */
transition: transform 1s;

设置多个值:transition: 属性 秒数,属性 秒数;

/* transition-property: transform; */
/* transition-duration:1s; */
/* transition-timing-function:ease; */
transition: transform 1s, width 1s, height 1s;

过渡属性transition-property

/*  形变 */
transition-property:transform;
/*  宽度 */
transition-property:width;
/*  外边距 */
transition-property:margin;

过渡持续时间transition-duration

/*尽量不超过0.5s*/
transition-duration: 0.5s;

过渡函数transition-timing-function

  • ease: 开始和结束慢,中间快。默认值。

  • linear: 匀速。

  • ease-in:开始慢。

  • ease-out: 结束慢。

  • ease-in-out: 和 ease 类似,但比 ease 幅度大。

过渡延迟时间transition-delay

transition-delay: 1s;

设置形变旋转原点

transform-origin: 0 0;

以动画的形式从 0 到 45 度,这就是过渡效果。

overflow(设置溢出)

正常情况下内容超出容器,会溢出。

  • 设置成 hidden。会把溢出的内容隐藏。

    overflow: hidden;
    
  • 设置成 auto,如果哪边溢出哪边就显示滚动条

    overflow: auto;
    

动画效果

动画与过渡的区别:

过渡效果通常用户与浏览器进行交互(例如 hover)

动画效果,可以交互,也可以在网页加载时直接执行,并且可以让效果更复杂。

动画属性(animation)

  • animation-name: 规定需要绑定到选择器的 keyframe 名称...

  • animation-duration: 规定完成动画所花费的时间,以秒或毫秒计。

  • animation-timing-function: 规定动画的速度曲线函数.

  • animation-delay: 规定在动画开始之前的延迟。

  • animation-iteration-count: 规定动画应该播放的次数。infinite 无限次

keyframes(定义动画)

  1. 按百分比指定动画
  2. from...to...指定动画

注意:开始与结束相同,可以让动画更平滑

@keyframes anim {
  0% {
    transform: translate(0px, 0px);
  }

  100% {
    transform: translate(900px, 100px);
  }
}

/* from:0%, to:100%  */
    from{
    	transform: rotate(0deg);
    }
    to{
    	transform: rotate(360deg);
    }

停止动画效果

animation-play-state: paused;

旋转唱片

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        *{
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        @keyframes spin {
            100%{
                transform: rotate(360deg);
            }
        }
        img{
            height: 300px;
            border-radius: 50%;
            animation: spin 2s linear infinite ;
        }
        img:hover{
            animation-play-state: paused;
        }
    </style>
</head>
<body>
<div class="img">
    <img src="../images/jay.jpg" alt="">
</div>
</body>
</html>

flex 布局

flex 是 flexible Box 的缩写,意为"弹性布局”,用来为盒状模型提供最大的灵活性,任何一个容器都可以指定为 flex 布局。这是一种更先进的布局方式,可以让网页布局更简洁,更易于维护。

flex布局的元素会把自己的一级子元素排成一行,并将他们变成可以伸缩,易排列的盒子。当我们为父盒子设为 flex 布局以后,子元素的 float、clear 和 vertical-align 属性将失效。

伸缩布局=弹性布局=伸缩盒布局=弹性盒布局=flex 布局

flex 布局原理

就是通过给父盒子添加 flex 属性,来控制子盒子的位置和排列方式

.box{
  display: flex;
}

此容器会变成一个flex容器(flex container),容器内部的元素被称为flex项目(flex item),在这个容器内部浮动会失效,通过设置flex容器的css样式,可以改变内部项目的布局方式。

基本概念

将元素设置为 display:flex;元素会变为一个 flex 容器。容器内部的元素为 flex 元素或者叫 flex 项目(flex-item)。

  • main axis:主轴
  • cross axis:交叉轴

Flex布局的基本概念

flex 容器中的默认效果

父元素是默认充满宽度的

  1. flex 项目在 flex 容器中延主轴排列。并且块元素不会独立成行。
  2. flex 项目高度适应 flex 容器高度(同行内元素)

设置 flex 容器

关于主轴的属性

  • flex-direction:

    设置 flex 项目排列方向,设置 主轴 的方向

    flex-direction是flex控制横向延展还是纵向延展的属性。

    值:

    • row(默认值): 主轴为水平方向,起点在左端从左到右

      row-reverse: 主轴为水平方向,起点在右端从右到左 column: 主轴为垂直方向,起点在上沿从上到下 column-reverse: 主轴为垂直方向,起点在下沿从下到上

    注意:使用这个属性之前一定要确定好主轴是哪个

  • justify-content:

    flex 项目在 主轴 的排列方式

    设置 主轴 上的子元素排列方式

    值:

    • flex-start(默认值): 左对齐 从头部开始 如果主轴是 x 轴,则从左到右 flex-end: 右对齐 从尾部开始排列 center: 居中 在主轴居中对齐(如果主轴是 x 轴则水平居中) space-between: 两端对齐,项目之间的间隔都相等 平分剩余空间 space-around: 每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍。先两边贴边 再平分剩余空间(重要) 类似于每个项目的 margin-left、margin-right 相等。

关于交叉轴的属性

  • align-items:

    flex 项目在 交叉轴 的排列方式

    设置侧轴上的子元素排列方式在子项为单项(单行)时使用

    值:

    • flex-start: 交叉轴的起点对齐。 flex-end: 交叉轴的终点对齐。 center: 交叉轴的中点对齐。 stretch(延申)(默认值):如果项目未设置高度或设为 auto ,将占满整个容器的高度。
  • align-content:

    设置交叉轴上的子元素排列方式(多行)只能用于子项出现换行的情况(多行),在单行下是没有效果的。

    值:

    • flex-start(默认值): 左对齐 从头部开始 如果主轴是 x 轴,则从左到右 flex-end: 右对齐 从尾部开始排列 center: 居中 在主轴居中对齐(如果主轴是 x 轴则水平居中) space-between: 两端对齐,项目之间的间隔都相等 平分剩余空间 space-around: 每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍。先两边贴边 再平分剩余空间(重要) 类似于每个项目的 margin-left、margin-right 相等。

其他属性

  • flex-wrap:

    设置子元素是否换行

    如果不设置换行,如果一行要满了,则项目的宽度会缩小。

    默认的子元素是不换行的,如果装不开,会缩小子元素的宽度,放到父元素里面。

    值:

    • nowrap:不换行;

      wrap:换行。

  • flex-flow:

    复合属性,相当于设置了 flex-direction 和 flex-wrap.

    flex-flow: row wrap; = flex-direction: row; + flex-wrap: wrap;

设置 flex 项目

  • flex-grow:属性定义项目的放大比例,默认为 0 ,空间充足,等比例补全。

  • flex-shrink:定义了项目的缩小比例,默认为 1 ,即如果空间不足,该项目将缩小。

  • flex-basis:主轴排列为宽度,交叉轴排列为高度,设置 px ,默认值为 auto。

  • flex:综合上面的三个样式。flex 属性定义子项目分配 剩余空间 ,用 flex 来表示占多少份数(fraction)。

    如果不设每个项目(3 个)的宽度只设容器宽度,那么

    /* 1 份 */
    flex: 1;
    /* 1 份 2 份 1 份 */
    flex: 1;
    flex: 2;
    flex: 1;
    
  • align-self:flex 项目的对齐方式,控制子项自己在侧轴上的排列方式。

    align-self 属性允许单个项目有与其他项目不一样的对齐方式,可覆盖 align-items 属性。默认值为 auto,表示继承父元素的 align-items 属性,如果没有父元素,则等同于 stretch.

    值:

    • auto flex-start flex-end center baseline stretch
  • order 属性:

    定义项目的排列顺序

    数值越小,排列越靠前,默认为 0

    注意: 与 z-index 不一样。

写 flex 布局的大概思路

  1. 将容器转换为 flex 容器。 display: flex;

  2. 先设置主轴方向

    (默认的) x 轴

    flex-direction: row;

    y 轴

    flex-direction: column;

  3. 设置主轴上子元素的排列方式(水平居中) justify-content: flex-start / flex-end / center / space-between / space-around

  4. 设置侧轴上子元素的排列方式(垂直居中) 单行找 align-items 多行找 align-content (单行) align-items: flex-start / flex-end / center / stretch (多行) 前提是要换行 flex-wrap:wrap; align-content: flex-start / flex-end / center / space-around / space-between / stretch

grid 布局

grid布局与flex布局对比

grid布局可以为网页提供更强大的布局功能,它与flex布局的区别是。

  • flex布局为一维布局,一般一行或一列的布局使用flex布局。
  • grid布局为二维布局,同时需要兼顾行与列的布局,可以使用gird布局。

如果不考虑兼容问题,flex布局和grid布局可以很好地替代浮动布局。

grid布局基本概念

grid容器的水平区域成为行(row),垂直区域成为列(column),行与列之间的交叉是单元格(cell),划分网格的线称为网格线(gird line),了解了这些基本概念之后,就可以开始用相应的css属性设置grid容器中的项目了

display: grid;

grid 容器属性

  • grid-auto-flow

    • row 默认排列方式(可以不写) 从左到右 从上到下
    • colum 竖着排列 从左到右 从上到下
  • grid-template-columns与grid-template-rows

    按像素来设置单元格 单元格与 grid 项目不一样的

    grid-template-columns: 100px 100px 100px;
    grid-template-rows: 100px 100px 100px;
    

    按比例来设置单元格

    grid-template-columns: 100px 1fr 2fr;
    grid-template-rows: 100px 100px 100px;
    

grid 项目 在 单元格 中的 对齐方式

  • justify-items:

    stretch 默认值 水平拉伸 start 单元格开始的位置(左) end 单元格结尾的位置(右) center 单元格居中的位置(中)

    值:

    • start 左 end 右 center 中 stretch 水平拉伸
  • align-items:

    stretch 默认值 垂直拉伸 start 单元格开始的位置(上) end 单元格结尾的位置(下) center 单元格居中的位置(中)

    值:

    • start 上

      end 下

      center 中

      stretch 垂直拉伸

单元格 在整个 grid 的 容器 中的 对齐方式

  • justify-content:

    值:

    • start

      end

      center

      stretch

  • align-content:

    值:

    • start

      end

      center

      stretch

  • grid-auto-columns: 溢出列的尺寸

    值:

    • 数字 px;
  • grid-auto-rows:

    溢出行的尺寸

    值:

    • 数字 px;

grid 项目属性

grid 项目对齐方式

  • justify-self:

    值:

    • start 左 end 右 center 中 stretch 水平拉伸
  • align-self:

    值:

    • start 上 end 下 center 中 stretch 垂直拉伸

单元格合并

  • 横向合并单元格

    grid-columns-start: 数字;

    grid-columns-end: 数字;

    简写:

    grid-columns: 数字 / 数字;

  • 纵向合并单元格

    grid-rows-start: 数字;

    grid-rows-end: 数字;

    简写:

    grid-rows: 数字 / 数字;

image-20220318205526338

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style type="text/css">
      .container {
        display: grid;
        width: 800px;
        height: 500px;
        border: 1px solid red;

        /* (可以不写)默认排列方式 从左到右 从上到下 123 456 789 */
        grid-auto-flow: row;

        /* 按像素来设置单元格 单元格与grid项目不一样的 */
        grid-template-columns: 100px 100px 100px;
        grid-template-rows: 100px 100px 100px;

        /* 溢出列的尺寸 */
        grid-auto-columns: 50px;
        /* 溢出行的尺寸 */
        grid-auto-rows: 50px;
      }

      .item {
        border: 1px solid red;
      }

      .first {
        /* 横向合并单元格 */
        /* grid-column-start: 2;
            grid-column-end:4; */
        grid-column: 2 / 4;
        /* 纵向合并单元格 */
        grid-row: 2 / 4;
        /* grid-row-start: 2; */
        /* grid-row-end:4;  */

        /* 设置grid项目的对齐方式 */
        /* justify-self: center;
            align-self: center; */
      }
    </style>
  </head>

  <body>
    <div class="container">
      <div class="item first">1</div>
      <div class="item">2</div>
      <div class="item">3</div>
      <div class="item">4</div>
      <div class="item">5</div>
      <div class="item">6</div>
      <div class="item">7</div>
      <div class="item">8</div>
      <div class="item">9</div>
      <!-- <div class="item">10</div>
        <div class="item">11</div> -->
    </div>
  </body>
</html>

媒体查询

响应式页面概述

响应式页面

这个是bootstrap的中文文档网站,大家可以用chrome浏览器来模拟手机端的浏览效果,可以看到手机端和电脑端访问同一个网页时,都能获得比较好的浏览体验。也就是说,一套代码可以同时适应多个设备。这样的网页就是响应式网页。

这样的网页,就是基于媒体查询实现的。

这里需要特别注意的是,我们访问同一个网站的地址,用手机可以正常浏览,用电脑也可以正常浏览,这并不一定就是响应式页面,例如晓舟报告官网就是响应式的,它只是针对终端设备的不同,展示了两套代码而已。响应式页面强调的是一套代码。

媒体查询

通过媒体查询,我们让css检测到浏览器视窗的展示尺寸,然后根据不同的浏览器视窗尺寸设置不同的样式,进而实现了同一套代码适应不同设备的功能。

max-width

媒体查询是CSS3中增加的新特性,可以使用@media来定义不同的条件和样式,窗口尺寸(或设备尺寸)满足指定条件的时候才会应用指定的样式,实例代码如下所示。

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<meta http-equiv="X-UA-Compatible" content="ie=edge">
	<title>Document</title>
	<style>
		.box{
			width:200px;
			height:200px;
			background-color: red;
		}
        /* 小于指定宽度,样式生效 */
		@media screen and (max-width:600px){
			.box{
				background-color: blue;
			}
		}
	</style>
</head>
<body>
	<div class="box"></div>
</body>
</html>

首先我们来看上面代码的效果,当全屏打开浏览器的时候(PC端的浏览方式),我们可以看到div元素的背景色为红色,当我们将浏览器的窗口缩小(移动端的浏览方式),当浏览器尺寸宽度小于600px的时候,元素的背景色会变成蓝色,这就是利用媒体查询实现的最基本的响应式页面,同一个文件,在不同设备上呈现着不同的样式。

在上面的代码中,max-width定义的就是标准,符合标准就会让下面的样式生效,max-width这个标准的意思就是:小于指定宽度,样式生效。

min-width

同样,我们也可以定义“大于指定宽度,样式生效”,实例代码如下所示。

@media screen and (min-width:600px){
    .box{
        background-color: blue;
    }
}

上述代码与demo01的效果刚好相反,PC端呈现蓝色,移动端呈现红色,min-width的意思是:大于指定宽度,样式生效。

多个标准

我们也可以给一个媒体查询定义多个标准,实例代码如下所示。

@media screen and (min-width:600px) and (max-width:900px){
    .box{
        background-color: blue;
    }
}

通过上面的方法,我们可以定义一个有多个标准的媒体查询,在上面的代码中,窗口大于600px并且小于900px的时候,样式生效,我们可以将浏览器窗口由大到小的收缩,可以看到元素颜色变化了两次。

响应式页面的缺点

在真实项目开发中,响应式页面并不常用,主要是因为一下几点。

  1. 为终端定制的页面,用户体验更好。
  2. 响应式页面代码量会增多,影响网页性能。
  3. 网页后期维护成本增加。

除非网页具备以下特点:

  1. 网页本身并不复杂。
  2. 对用户体验要求不高。
  3. 希望多终端访问,又希望降低开发成本。

就可以选择响应式页面了。

rem布局

PC端页面的网页重构,我们使用最多的单位是px。因为在PC端,大部分页面效果我们都可以设置成固定尺寸,但是在手机端,这种方案是不可行的,我们必须要按照百分比呈现页面,才能保证网页在任何设备上可以正常显示。为了实现这样的功能,我们可以将所有的尺寸都设置成百分比,但是这样会给前端开发带来大量的计算工作。为了实现百分比的效果,又能省去大量的计算工作,我们使用rem布局。

单位概述

  1. px:像素

  2. em:相对于父级的 font-size 值,父级的 font-size 值越大,子级的 em 就越大

  3. rem:相对于 html 标签的 font-size 值

  4. html font-size: N px; 1rem 代表 N px; 10rem 代表 10N px;

根据移动端浏览器宽度通过 js 来自适应 rem 单位

利用rem单位可以制作出适应不同尺寸设备的页面。

首先考虑一个问题,rem的参照物是html元素的font-size属性,那么如果html的font-size属性不变的话,我们使用的rem单位仍然是一个固定的单位,所以我们需要做的是让html元素的font-size属性在不同的设备中设置不同的值,这就需要一段js代码了,代码如下所示(fontsizeset.js)

(function (doc, win) {
var docEl = doc.documentElement,
  resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
  recalc = function () {
    var clientWidth = docEl.clientWidth;
    if (!clientWidth) return;
    docEl.style.fontSize = 100 * (clientWidth / 720) + 'px';
  };
if (!doc.addEventListener) return;
win.addEventListener(resizeEvt, recalc, false);
doc.addEventListener('DOMContentLoaded', recalc, false);
})(document, window);

我们并不需要理解上面的这段代码是如何执行的,只需要知道这段代码可以检测设备的尺寸,并通过设备的尺寸设置html元素的font-size值,这个font-size值会根据设备尺寸的变化而变化,这样我们设置相同的rem值,就会起到百分比的作用了。

来看一个实际案例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
	<!-- 在html中引入fontsizeset.js文件 -->
    <script src="fontsizeset.js"></script>
    <style>
        *{
            margin:0px;
            padding:0px;
        }       
        .box{
            width: 3.6rem;
            height:3.6rem;
            background-color: red;
        } 
    </style>
</head>
<body>
    <div class="box"></div>
</body>
</html>

在上面的代码中,我们将div的宽和高都设置成了3.6rem,用浏览器打开,发现元素宽度与高度相同,并且宽度始终是窗口宽度的50%。这说明rem布局与百分比布局能实现相同的效果。

四、设计稿量尺

我们再从web开发流程的角度来看,为什么rem布局比百分比布局更加简便,使用rem布局的流程如下所示:

  1. 首先,我们拿到设计师的设计稿,通常设计稿的宽度为640px、720px、1080px。
  2. 然后再来看看我们的fontsizeset.js文件中的一段代码,第二个数字720就是设计稿的宽度,如果设计稿是1080px,我们需要将fontsizeset.js中的720改成1080。
docEl.style.fontSize = 100 * (clientWidth / 720) + 'px';
  • 最后量尺的时候,如果设计稿中的元素尺寸为x,那么元素的尺寸我们就可以设置成x/100rem(这个100就是上面代码中的第一个数字,具体示例可以看下一节内容)。

我们引入的js文件是720px的设计稿,那么假如设计稿中有一个360px的元素,则该元素广告就是原设计稿的一半,这样我们通过换算可以得到这个元素在网页中的尺寸是3.6rem,所以当我们设置成3.6rem的时候,不管视窗的尺寸如何变化,元素的宽度始终都是整个页面的50%。

通过上述的方法,就可以很容易制作出按百分比排列的页面布局了,这就是rem布局的优势。