前端基础之CSS篇

397 阅读15分钟

CSS选择器

选择器的种类

  1. 类型、类和ID选择器
  • 类型(标签)选择器:p
  • 类选择器:.class
  • ID选择器:#id
  1. 属性选择器

a[href="http://example.com"]

  1. 伪类与伪元素
  • 伪类:a:hover
  • 伪元素:p::before
  1. 运算符
  • 后代选择器:div p,空格区分,表示选择div元素的所有p元素后代
  • 子代选择器:div > p,>符号,表示选择div元素的直接后代,孙子元素不受影响
  • 相邻兄弟选择器:div + p,+符号,表示选择位于div元素后面,并且与div元素拥有共同父元素的p元素
  • 通用兄弟选择器:div ~ p,~符号,表示选择div元素后面的所有p元素
  1. 通用选择器:*
  2. 结构化伪类:tr:nth-child(3)

选择器的优先级

选择器的优先级由四个部分相加,可以认为是个十百千四位数的四个位数:

  • 千位:声明在style的属性(内联样式)则该位得一分。
  • 百位:选择器中包含ID选择器,则该位得一分。
  • 十位:选择器中包含类选择器、属性选择器或者伪类则该位得一分。
  • 个位:选择器中包含元素、伪元素选择器则该位得一分。

盒模型

盒模型是CSS的核心概念,描述了元素如何显示,以及如何相互作用、相互影响。页面中的所有元素被看作一个矩形盒子,这个盒子包含元素的内容(content)、内边距(padding)、边框(border)和外边距(margin)。

块级盒子(block box)与内联盒子(inline box

CSS中有两种盒子:块级盒子和内联盒子,它们在页面流和元素之间的关系方面表现出不同的行为。

块级盒子

  • 盒子会在内联的方向上扩展并占据父容器在该方向上的所有可用空间,在绝大多数情况下意味着盒子会和父容器一样宽
  • 每个盒子都会换行
  • width和height属性的配置可以正常生效
  • 内边距(padding),外边距(margin)和边框(border)会将其他元素从当前盒子周围推开
  • 例如:p、div、article、aside、audio

内联盒子(inline box)

  • 盒子不会换行
  • width和height属性将不起作用
  • 垂直方向的内边距、外边距以及边框会被应用但是不会把其他处于inline状态的盒子推开
  • 水平方向的内边距、外边距以及边框会被应用且把其他处于inline状态的盒子推开
  • 例如:span、script、img、a、b

区别

  1. 格式

默认情况下,块级元素会新起一行。

  1. 内容模型

一般块级元素可以包含行内元素和其它块级元素,这种结构上的区别可以使块级元素创建比行内元素更大型的结构。

拓展display属性

可以使用display属性改变生成的盒子类型。

  • 如通过把display属性设置为block,让span变得跟块级元素一样显示,另起一行,可设置宽高。
  • display属性设置为inline,将元素内联显示,即都在同一行内,不能设置宽高。
  • 如果把display设置为none,还可以让浏览器不为相应的元素生成盒子,即元素及其包含的内容不会显示出来,也不会占用文档中的空间。
  • 如将display设置为inline-block,可以打破行内元素与块级元素壁垒,将对象呈递为内联块级,即元素既显示在同一行内,也可设置起宽高。副作用是会造成内联块级元素间有空格间隙,解决方法有两种:设置元素margin为负值;设置父容器font-size为0,子元素font-size为1rem。

盒模型

完整的CSS盒模型应用于块级盒子,内联盒子只是用盒模型中定义的部分内容。模型定义了盒的每个部分:margin、border、padding、content,合在一起就可以创建我们在页面上看到的内容。为了增加一些额外的复杂性,有一个标准的和替代(IE)的盒模型。

  • content box:这个区域是用来显示内容,大小可以通过设置width和height
  • padding box:包围在内容区域外部的空白区域,大小通过padding相关属性设置
  • border box:边框盒包裹内容盒内边距。大小通过border相关属性设置
  • margin box:这是最外面的区域,是盒子和其他元素之间的空白区域。大小通过margin相关属性设置

给元素应用的背景会作用于元素内容和内边距。有一个与边框类似的属性,即轮廓线(outline),这个属性可以在边框盒子外围画出一条线,但这条线不影响盒子的布局,也就是不会影响盒子的宽度和高度。

img

  1. 标准盒模型(content-box)

在标准盒模型中,如果你给盒设置width和height,实际设置的是content box,也就是元素可渲染内容区域的宽度和高度。这时候添加边框盒内边距并不会影响内容盒子的大小,但会导致整个元素盒子变大。

  1. 替代(IE)盒模型

通过修改box-sizing属性可以改变计算盒子大小的方式。box-sizing的默认值为content-box,将其修改为border-box,则width和height的值将会包含padding和border

元素布局

文档流

浏览器布局理论:

  • 围绕元素内容添加任何padding、border、margin来布置单个元素盒子,这就是盒模型。默认情况下,块级元素的内容宽度是其父元素宽度的100%,并且与其内容一样高。内联元素高宽与他们的内容高宽一样。不能对内联元素设置高宽,他们只是位于块级元素的内容中。如果要以这种方式控制内联元素的大小,则需要将其设置为类似块级元素display:block
  • 以上解释了单个元素,元素相互之间如何交互呢?正常的布局流只是将元素放置在浏览器视口内的系统。默认情况下,块级元素在视口中垂直布局,每个都将显示在上一个元素下面的新行上,并且他们的外边距将分隔开他们。
  • 内联元素表现不一样,他们不会出现在新行上;相反,它们互相之间以及任何相邻的文本内容位于同一行上,只要在父块级元素的宽度内有空间可以这样做。如果没有空间,那么溢流的文本或元素将向下移动到新行。
  • 如果两个相邻元素都在其上设置外边距,并且外边距接触,则两个外边距中的较大者保留,较小的一个消失,这就是外边距折叠。

position

定位的整个想法是允许我们覆盖正常的文档布局流行为,已产生有趣的效果,使得元素可以浮动在页面其他部分顶部或者始终停留在浏览器窗口内的相同位置。

  1. 静态定位(static)

静态定位是每个元素获取的默认值,意味着将元素放入它在正常文档布局流中的正常位置。

  1. 相对定位(relative)

元素仍然占据在正常的文档流中,但此后,可通过设置top、right、bottom、left属性,使该元素相对于初始位置平移一定距离。无论是否位移,相对定位的元素仍会在文档流中占据初始的空间。因此,平移元素会导致它遮挡其他元素。相对定位事实上是常规文档流定位模型的一部分,因为元素还是相对于它在常规流中的初始位置来定位。

  1. 绝对定位(absolute)

绝对定位会把元素拿出文档流,因此也就不会再占用原来的空间。同时,文档流中的其他元素会各自重新定位,仿佛绝对定位的那个元素没有存在过。绝对定位元素的包含块是距离它最近的定位祖先,也就是position属性设置为static之外任意值的祖先元素。如果没有这么一个定位祖先,那么它就相对于文档的根元素即html元素定位。

  • z-index:改变元素的堆叠顺序。z-index值越大,盒子在层叠中的次序就越靠近用户的眼睛。
  1. 固定定位(fixed)

与绝对定位的工作方式完全相同,只有一个主要区别,绝对定位是相对于html元素或其最近的定位祖先,而固定定位是相对于浏览器视口本身。

  1. sticky

是相对定位和固定定位的混合体,允许被定位的元素表现得像相对定位一样,直到它滚动到某个阈值点为止,此后它就变得固定了。未滚动时,它会影响周边元素布局。

  • 总结:定位的记忆要点是,是否会脱离正常文档布局流,定位的参照物(即包含块是什么)。

float

浮动盒子可以向左或向右移动,直到其外边沿接触包含块的外边沿,或接触另一个浮动盒子的外边沿。浮动元素会脱离文档流,因此不会再像非浮动元素一样影响其他元素。严格来讲,也并非如此,浮动的提出是为了实现文本包围图片的布局效果。实则如果浮动元素后面跟着的是常规文档流中的元素,那么这个元素的盒子就会当浮动元素不存在一样,该怎么布局就怎么布局。但是这个元素盒子的文本内容则会记住浮动元素的大小,并在排布时避开它,为其留出相应的空间。

  1. 清除浮动

要阻止行盒子环绕在浮动盒子外面,需要给包含行盒子的元素应用clear属性。

<style>
    .div1:after {
        content: '';
        clear: both;
        display: block;
    }
    img{
        float: left;
        width: 900px;
    }
    .div2{
        float: right;
        width: 125px;
    }
</style>
<div class="div1">
  <img src="../../images/browser.jpg">
  <div class="div2">
    <h2>title</h2>
    <p>content</p>
  </div>
</div>

由于浮动元素会被拿出文档流,所以div1元素的高度为0,如果要使其包住浮动元素,则需要清除浮动,常规做法是增加html节点,不过使用after伪元素,可以避免增加不必要的html元素。

  1. 块级格式化上下文(BFC)

规定页面必须自动包含突出的浮动元素,而且所有块级盒子的左边界默认与包含块的左边界对齐,元素也可以遵循有些规则建立自己内部的块级格式化上下文,规则包括:

  • display属性设置为inline-block或table-cell之类的元素;
  • float属性值不是none的元素;
  • 绝对定位的元素;
  • overflow属性值不是visible的元素

基于BFC给出上例的解决方案,首先明确上例清除浮动所解决的问题:div1自动包含浮动元素,div2自适应图片剩余宽度。

  • 给div1设置overflow: auto;,创建BFC,由于其规定必须自动包含突出的浮动元素,无需设置清除规则,div1包住浮动的图片,从而获得高度。
  • 给div2设置overflow: auto;,不需为其声明宽度和浮动,创建BFC,由于其规定BFC块级盒子左边界默认与包含块的左边界对齐,所以div2的宽度为自身盒子,因为它会自动调整以适应浮动元素旁边的剩余空间。
<style>
    img{
        float: left;
        width: 900px;
    }
    .div1.div2{
        overflow: auto;
    }
</style>

flex布局

Flexbox是CSS提供的用于布局的一套新属性,针对容器(弹性容器,flex container)和针对其直接子元素(弹性项,flex item)的两类属性。Flexbox可以控制弹性项的如下方面:

  • 大小,基于内容及可用空间;
  • 流动方向,水平还是垂直,正向还是反向;
  • 两个轴向上的对齐与分布;
  • 顺序,与源代码中的顺序无关。
  1. flex-flow

针对弹性容器的属性,可以将flex-direction: row;flex-wrap: wrap;缩写为flex-flow: row wrap。flex-direction属性确定弹性盒子主轴的方向,默认为行,flex-wrap设置弹性项在主方向上是否可以换行。

  1. 水平、垂直对齐
  • 沿主轴的排列叫排布,用于指定排布方式的属性是justify-content,当指定为center时,会居中所有项,多余的空间等分后放到边缘项的外部。如果指定某弹性项一侧的外边距值为auto(如:margin-right: auto),而且在容器里那一侧还有空间,那么该外边距就会扩展占据可用空间。如此,可以实现让一项位于一侧,其他项位于另一侧的布局。

  • 沿辅轴的排列叫对齐,用align-items属性控制。

当弹性容器里面只有一个元素时,只要将弹性项的外边距设置为auto(margin: auto)即可实现该元素的水平垂直居中。这是因为Flexbox中各项的自动外边距会扩展填充相应方向的空间。

  1. 可伸缩的尺寸

Flex的意思是可伸缩,这体现在以下三个属性(针对弹性项使用)中:

  • flex-basis:控制项目在主轴方向上、经过修正之前的首选大小。可以是长度值,百分比,或关键字auto。设置auto的意思是,项目可以从对应的属性获得主尺寸(width或height),若未设置主尺寸,则根据其内容确定大小。
  • flex-grow:在通过flex-basis为每一项设置了首选大小后,如果有剩余空间,则通过flex-grow占比为其分配剩余空间。
  • flex-shrink:与flex-grow作用相反,配置当容器空间不够时,如何缩小。

flex是一个可以指定最多三个不同值的缩写属性,依次排序为flex-growflex-shrinkflex-basis,其中,只有flex-basis会取有单位值。

元素布局应用

水平垂直居中

  1. 内联元素
  • 水平居中:text-align: center;
  • 垂直居中:1.vertical-align: middle;该属性含义是,将行内块的垂直中心点与这行文本高度的中心点对齐,基于基线进行计算,行内块高度不一致时,需要共同指定vertical-align: middle;2.height:20px;line-height:20px;
  1. 块级元素(不确定元素宽高)
  <div class="container">
    <div class="center">center</div>
  </div>
  • flex实现:

    1. 单个元素时
    <style>
        .container{
            display: flex;
        }
        .center{
            margin: auto;
        }
    </style>
    
    1. 多个元素时
    <style>
        .container{
            display: flex;
            justify-content: center;
            align-items: center;
        }
    </style>
    
  • position实现

    <style>
        .container{
            position: relative;
        }
        .center{
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);   
        }
    </style>

左固定右自适应

  <div class="container">
    <div class="left">left</div>
    <div class="right">right</div>
  </div>
  1. flex实现 弹性项默认的配置为0 1 auto,左侧宽度可以通过width或者flex-basis指定,是否配置左侧缩放覆盖默认值,按需确认;右侧实则是要修改默认的flex-grow为1。
    <style>
        .container{
            display: flex;
        }
        .left{
            width: 200px;
            /* 按需配置是否缩放 */
            flex-shrink: 0;
            /* 可用以下设置替代 */
            /* flex: 0 0 200px; */
        }
        .right{
            flex-grow: 1;
            /* 也可用以下指定 */
            /* flex: 1; */
        }
    </style>
  1. position

父容器设置padding,将固定宽度的元素绝对定位,放到padding的宽度内,右侧设置width为100%即可。

    <style>
        .container{
            position: relative;
            padding-left: 200px;
        }
        .left{
            width: 200px;
            position: absolute;
            top: 0;
            left: 0;
        }
        .right{
            width: 100%;
        }
    </style>

CSS3动画

变化(transform)

变化包括旋转、变形、平移和缩放元素,甚至在三维空间里。

  1. 变化原点:通过transform-origin属性控制,默认情况下,变化是以元素边框盒子的中心作为原点。
  2. rotate:旋转,transform: rotate(45deg);,旋转45度角。
  3. translate:平移,transform: translate(100%, 0);,指定元素沿x轴、y轴平移的距离,值可以是任意长度值,像素、em或百分比都可以。百分比时,是相对于元素自身大小,而不是包含块大小。因此,不必知道元素有多大,就可以让它移动自身宽度的一倍距离。
  4. scale:缩放,transform: scale(2);
  5. skew:变形,transform: skewX(45deg);

transform的性能很好,因为它的计算只会影响相关元素的坐标系统,既不会改变元素内部的布局,又不会影响外部的其它元素。

过渡(transition)

过渡是一种动画,可以从一种状态过渡到另一种状态。比如,hover状态样式改变,可以通过transition配置动画效果。transition属性可以倍指定为一个或多个CSS属性的过渡效果,多个属性之间用逗号进行分隔。transition属性是一个简写形式,具体包括:

  1. transition-property:指定动画作用的属性
  2. transition-duration:动画持续时长
  3. transition-timing-function:动画效果变化函数
  4. transition-delay:动画延迟时长
<style>
    .left{
        background-color: #984040;
        transition: background 1s;
    }
    .left:hover{
        background-color: aqua;
    }
</style>

并非所有CSS属性都可以拿来实现过渡动画,多数情况下,涉及长度和颜色的都是可以的,这取决于能都计算值的中间状态。但是display的两个值block和none就没有中间状态,不能使用。

动画

CSS过渡是一种隐式动画,需要给浏览器指定两个状态,让浏览器在元素从一个状态过渡到另一个状态的过程中,给指定的属性添加动画效果。有时候,动画的范围不仅限于两个状态,或者要实现动画的属性一开始也不一定存在。CSS Animations规范引入关键帧的概念来实现这类动画。

<style>
@keyframes roll {
    from {
      transform: translateX(-100%);
      animation-timing-function: ease-in-out;
    }

    50% {
      transform: translateX(-100%) rotate(45deg) scaleX(1.1);
      animation-timing-function: ease-in;
    }

    to {
      transform: translateX(-100%) rotate(90deg);
    }
  }

  .animation {
    background-color: red;
    display: inline-block;
    width: 200px;
    height: 200px;
    animation-name: roll;
    animation-duration: 1.5s;
    animation-delay: 1s;
    animation-iteration-count: 3;
    animation-timing-function: linear;
    /* animation配置可简写 */
    /* animation: roll 1.5s 1s 3 linear; */
    transform-origin: bottom right;
  }
</style>

可以用动画来实现元素显隐的平滑过渡效果。

画三角形

<style>
    .div{
        width: 0;
        height: 0;
        border: 50px solid transparent;
        border-bottom: 100px solid red;
    }
</style>

画圆

<style>
    .div{
        width: 200px;
        height: 200px;
        border-radius: 100px;
    }
</style>

移动端适配

Less

宏,可直接复用的样式,还可以传参数