【Hello,前端!】用CSS画出缤纷世界 (下)| 青训营笔记

79 阅读9分钟

这是我参与「第四届青训营 」笔记创作活动的第3天

今天Richy将继续带来CSS部分的下半篇内容——CSS的进阶使用技巧。

特异度与优先级

随着我们写的项目越来越复杂,HTML元素越来越多,使用CSS选择器时常常我们会遇到两个甚至多个选择器选择的范围出现重合,即有一些元素被多个选择器选中并赋予了样式,例如下面这一段代码:

<body>
    <h1>
        <a class="linkto" href="/">用CSS画出缤纷世界</a>
    </h1>
</body>

<style>
    h1 a {
        color: blue;
    }
    .linkto {
        color: orange;
    }

此时的a标签同时被两个选择器选中并赋予了不同的样式属性,那么最终是哪一条规则生效了呢?

这里就要引入CSS的特异度规则了 在前面介绍的几种选择器里,每种选择器都是有不同的权重的:

  • id选择器,权重100
  • 类、属性、伪类选择器,权重10
  • 标签/元素名、伪元素选择器,权重1

除此之外,还有一些特殊情况:

  • 使用内联样式时,特异度权重为1000
  • 使用!important修饰将使得该条样式具有最高优先级,可以覆盖任意权重的通过一般形式设定的样式规则
  • *通配选择器以及被继承的值拥有最低的特异性,可以看做权重为0。
<button class="btn">普通按钮</button>
<button class="btn primary">主要按钮</button>
<button class="btn success">确认按钮</button>
<button class="btn warn">删除按钮</button>
<style>
    .btn {
        display: inline-block;
        padding: .36em .8em;
        margin-right: .5em;
        line-height: 1.5;
        text-align: center;
        cursor: pointer;
        border-radius: .3em;
        border: none;
        background: #e6e6e6;
        color: #333;
    }
    .btn.primary {
        color: #fff;
        background: blue;
    }
    .btn.success {
        color: #fff;
        background: green;
    }
    .btn.warn {
        color: #fff;
        background: red;
    }
</style>

效果演示地址

上面的代码中,我们通过基类btn设定了按钮的基础样式,然后通过特异度更高的.基类.子类选择器重设了子类的具体颜色样式,实现了基类代码的复用,这也是特异度规则的优越性。

Tips

我们在使用CSS时,一旦出现了这种多条规则作用于同一元素的情况,常常就会导致我们设定了某条属性却没有生效。此时我们可以通过F12快捷键打开控制台查看元素的CSS样式,分析我们的代码是否因为特异度等级较低而被其他的规则所覆盖了。

在特异度相等的情况下,后载入的规则会覆盖先载入的规则。

继承

某些属性在没有显示指定他的值的时候,就会从父元素直接继承对应属性的属性值。 例如:

<body>
  <p>This is a <em>test</em> of <strong>inherit</strong></p>
</body>

<style>
  body {
    font-size: 20px;
  }
  p {
    color: blue;
  }
  em {
    color: red;
  }
  strong {    
    font-size: 40px;
  }
</style>

效果演示地址

上面的代码中,<body>内部的<p><em><strong>都从<body>处继承了font-size属性,而<em><strong>又从<p>标签继承了color属性。同时我们也可以看到,<em>设定的color属性覆盖掉了继承的<p>的color属性,这也与上面我们说的继承具有最低的特异性相吻合。

Tips

并非所有的属性都会默认继承,一般来说:

  • 文本、排版等内容相关的属性,如font、color、text-align、line-heigh,是可继承的属性;
  • 边框、定位等布局相关的属性,如Padding、Margin、background、border,是非继承的属性。

初始值

CSS中每个属性都有一个初始值,例如background-color默认为transparent,margin-left初始值默认为0等。

在CSS代码中,我们也可以人为的使用initial关键字将属性重置为初始值。

    background: initial;

Tips

需要注意区分的是,初始值≠默认值,初始值是在CSS规范中为每个属性设定的初始值,而默认值是指在开发者没有进行显式声明某个属性的值时浏览器基于一定的规则赋予的缺省值。 默认值一般遵循一下原则获取:

  • 对于非继承属性,默认值为初始值initial
  • 对于继承属性,需要进一步判断:
    • 若对应元素为根元素,则默认值为继承值inherit
    • 若对应元素非根元素,则默认值为初始值initial

CSS求值过程

1. 确定声明值

综合对比浏览器默认样式表与开发者书写的样式表,选择其中没有冲突的声明作为css属性值。

2. 解决层叠冲突

首先,按照!important标识属性、开发者样式表、浏览器默认样式表的重要度顺序确定生效的规则。

若重要度相同,按照特异度规则比较特异度。

若特异度相同,以最后载入的规则为最终生效的规则。

3. 继承

对于没有声明具体值的属性,通过继承规则获取父元素的值。

4. 赋初始值

对于仍没有值的属性,赋予初始值。

CSS布局

CSS布局有多种模式,一般通过属性display进行设定

  • 常规流
    • 行级布局
    • 块级布局
    • 表格布局
    • Flex布局
    • Grid布局
  • 浮动
  • 绝对定位

元素盒子

  • 外边距margin
  • 边框border
  • 内边距padding
  • 内容content

width

  • 指定content box的宽度
  • 取值可以是具体值、百分数、auto
  • auto由浏览器根据content的内容自行计算确定
  • 百分数相对于容器的content box宽度计算

height

  • 指定content box的高度
  • 取值可以是具体值、百分数、auto
  • auto由浏览器根据content的内容自行计算确定
  • 百分数相对于容器的content box高度计算
  • 只有容器有指定高度时,百分数才生效

padding

  • 指定元素四个方向的内边距
  • 取值可以是具体值、百分数、auto
  • 百分数相对于容器的宽度设定

border

  • 指定边框样式、粗细和颜色
  • 同样可以指定不同方向

margin

  • 指定元素四个方向的内边距
  • 取值可以是具体值、百分数、auto(可以用于水平居中)
  • 百分数相对于容器的宽度设定
  • 在垂直方向上两个相邻元素都有margin时会取较大的margin而不是简单相加

box-siziing: border-box

  • 会将padding、border合并计算width

overflow

  • visible,始终显示所有内容
  • hidden,不显示超出部分
  • scroll,超出时滚动

常规流布局

行级盒子

  • 行级盒子会和其他行级盒子一起放在同一行内布局,当超出范围时会进行自动换行
  • 行为模式类似于段落<p>标签内的文本
  • widthheight不适用,由其内容撑开宽高
  • <span><em>等都是典型的行级盒子元素

行级排版上下文

  • IFC,Inline Formatting Context
  • 只包含行级盒子的容器会创建一个IFC
  • IFC内部排版规则
    • 盒子在一行内水平摆放
    • 一行显示不下时换行
    • text-align决定一行盒子的水平对齐方向
    • vertical-align决定一个盒子在行内的垂直对齐方向
    • 避开浮动元素排版

举个栗子

<p>
    这是一个IFC布局的盒子,这里有一个长单词:Hippopotomonstrosesquippedaliophobia
    <img src="https://assets.codepen.io/59477/cat.png" alt="">
    这是一个inline-block:<em>inline block</em>
</p>

<style>
    p {
        width: 10em;
        background: yellow;
    }

    em {
        display: inline-block;
        width: 3em;
        background: blue;
    }
</style>

效果演示地址

块级盒子

  • 块级盒子每个元素独占一行,不进行并列摆放
  • 可以设置widthheight
  • <body><p>等都是典型的块级盒子元素

块级排版上下文

  • BFC,Block Formatting Context
  • 某些容器会自动创建BFC
    • 根元素
    • 浮动、绝对定位、inline-block
    • flex子项和grid子项
    • overflow值不是visible的块盒
    • display: flow-root;
  • BFC内部排版规则
    • 盒子从上到下摆放
    • 垂直margin合并
    • BFC内部盒子的margin不会与外部的合并
    • BFC不会和浮动元素重叠

举个栗子

<span>
    这段话被
    <div>
        <img src="https://assets.codepen.io/59477/cat.png" alt="">
    </div>
    插入了一张图片
</span>

<style>
    span {
        background: yellow;
    }

    div {
        background: blue;
    }
</style>

效果演示地址

Flex弹性盒子

  • 一种新的排版上下文
  • 可以自由控制盒子的
    • 摆放流向
    • 摆放顺序
    • 盒子的宽高
    • 水平垂直方向上的对齐
    • 是否允许折行

举个栗子

<ul>
    <li>首页</li>
    <li>课程</li>
    <li>直播</li>
    <li>咨询</li>
    <li>活动</li>
    <li>开放社区</li>
    <li>商城</li>
    <li>APP</li>
    <li>插件</li>
</ul>

<style>
    ul {
        display: flex;
    }

    li {
        flex:1;
        text-align: center;
        line-height: 100px;
        list-style: none;
        background: lightblue;
        border-right: 1px solid grey;
    }

    li:last-child {
        border: none;    
    }
</style>

效果演示地址

Grid网格布局

  • Grid网格布局同样是CSS一种新的布局模式
  • Grid布局和flex布局的实质性区别是:
    • flex是一维布局,只能处理一个上的布局,一行或者是一列
    • Grid布局是二维布局 ,将容器划分成了即一个个的网格,将网格元素放在行列对应的位置上,以完成布局

举个栗子

 <div class="container">
    <div class="grid one">One</div>
    <div class="grid two">Two</div>
    <div class="grid three">Three</div>
    <div class="grid four">Four</div>
    <div class="grid five">Five</div>
    <div class="grid six">Six</div>
</div>

<style>
  .container {
    padding: 40px;
    display: grid;
    grid-template-columns: repeat(3,200px);
    grid-gap: 20px;
    grid-template-rows: 100px 200px;
  }
  .grid {
      text-align: center;
      font-size: 200%;
      color: #fff;
  }
  .one {
      background-color: lightblue ;
  }
  .two {
      background-color: grey;
  }
  .three {
      background-color: orange ;
  }
  .four {
      background-color: lightgreen;
  }
  .five {
      background-color: red;
  }
  .six {
      background-color: pink;
  }
</style>

效果演示地址

Float浮动

  • 浮动就是使元素脱离原来的文本流,在父元素中浮动起来,实现文本环绕的效果。
  • 设置float属性可以使元素变为float浮动元素
    • none,不浮动
    • left,向左浮动
    • right,向右浮动
  • 不论是块级上下文还是行级上下文内都可以设置浮动
  • 被设置为浮动后,元素自动变为块级元素,且不能更改为行级
  • 元素浮动后,原本处于下方的元素会上移,其中的内容会环绕浮动元素
  • 浮动会使元素完全脱离文档流,在文档中将不再占据位置
  • 浮动元素会在容器内一直上浮至上边界遇到其他浮动元素
  • 浮动元素不会撑开父元素高度,所以浮动元素的宽高要注意设定为合适的值

举个栗子

<p>
<img src="https://assets.codepen.io/59477/cat.png" alt="">
山西河北河南等地出现大到暴雨:昨日08时至今日06时,内蒙古中部偏南地区、山西南部、河北南部、河南、湖北北部、安徽北部、浙江北部等地部分地区出现大到暴雨,河南郑州、南阳、驻马店、河北衡水和石家庄、浙江绍兴等局地大暴雨(100~181毫米);上述地区最大小时降雨量40~80毫米,河南郑州惠济区局地103.7毫米;上述部分地区出现8~10级雷暴大风,河南、山西局地12~13级并伴有冰雹。江淮江南华南等地出现高温:昨日,江淮、江南、华南及河南中南部、湖北、四川盆地、贵州东部、新疆南疆盆地等地出现35℃以上高温,浙江、福建、江西、湖南、广东、重庆、新疆南疆盆地等地部分地区最高气温有38~40℃,浙江丽水及福建三明等局地达41℃。
</p>

<style>
  p {
    background-color: lightblue;
  }
  img {
    float: left;
  }
</style>

效果演示地址

绝对定位

  • 设置position属性值为absolutefixed时成为元素的绝对定位
  • absolute是相对于第一个非static定位的父元素进行定位,元素的位置通过 "left", "top", "right" 以及 "bottom" 属性进行设定。
  • fixed是相对于浏览器窗口进行定位,元素的位置通过 "left", "top", "right" 以及 "bottom" 属性进行设定。

举个栗子

 <div class="container">
    <p>正常的文档流<p>
    <p>正常的文档流<p>
    <p>正常的文档流<p>
    <p>正常的文档流<p>
    <p>正常的文档流<p>
    <div class="item absolute">Absolute</div>
    <div class="item fixed">Fixed</div>
</div>

<style>
  .container {
    width: 300px;
    height: 200px;
    margin: 50px;
    background-color: grey;
    position: relative;
  }
  
  p {
    color: white;
  }
  
  .item {
    width: 100px;
    height: 30px
  }
  
  .absolute {
    background-color: lightblue;
    position: absolute;
    top: 20px;
    left: 20px;
  }
  
  .fixed {
    background-color: orange;
    position: fixed;
    top: 20px;
    left: 20px;
  }
</style>

效果演示地址

End

本文通过整理课堂笔记,结合网络上相关资料写成。CSS中知识体系和规范细节发展到如今已经非常繁杂,本文只是浅显的通过一些例子介绍CSS中的一些基础概念与重点知识,想要深入学习更多的CSS知识,可以移步MDN官方教程