CSS,层叠样式表(英语:Cascading Style Sheets),是一种用来为结构化文档 (如:HTML文档) 添加样式 (字体、颜色、间距等) 的计算机语言,由 W3C 定义和维护。当前最新的版本是 CSS2.1,为W3C的推荐标准。CSS3(2011年) 已经被现代浏览器支持。

CSS发展历史

  1. 1994年哈肯.维姆.莱提出了CSS的最初建议。伯特.波斯加入一起设计CSS。
  2. 1997年初,W3C内组织了专门管CSS的工作组,其负责人是克里斯.里雷。
  3. 1998年5月W3C发表了CSS2,CSS2.1修改了CSS2中的一些错误,删除了其中不被支持的内容和增加了一些已有浏览器的扩展内容。
  4. 从2001年开始CSS被分为了多个单独的模块,统称为CSS3。这些模块有:
    • CSS 选择器 level 3
    • CSS 媒体查询 level 3
    • CSS Color level 3
    • ……

周边工具

CSS 学习资源

  1. MDN 查询关键字,遇到不会的 CSS 属性就去查阅MDN
  2. CSS Tricks,可以根据属性搜索很多好看的CSS效果;
  3. Google: 阮一峰老师 css
  4. 张鑫旭大神的 240 多篇 CSS 博客
  5. Codrops 炫酷 CSS 效果
  6. CSS揭秘
  7. CSS 2.1 中文 spec
  8. Google 搜索 CSS Generator ,可以生成css样式

CSS 开始写

引入 CSS 的几种方式

  • 行间 <div style="color:red;"></div>
  • 内联 <style>div{color: red}</style>
  • 外部 <link href="index.css" rel="stylesheet">
  • import引入 @import url(./index.css)

布局小技巧

  • HTMLdivspan 外,都有默认样式,所以在布局之前我们通常会清除一些标签的默认样式,如:

    body,p,h1,h2,dl,dt {
    margin: 0;
    }
    ul,ol {
    list-style: none;
    padding: 0;
    margin: 0
    }
    /* 通常不建议这么写 *{margin: 0; margin: 0} */
    
  • 清除浮动,如子级用浮动布局,则需给父级添加浮动清除代码,代码通常写法,给父级添加 clearfix 类选择器:

    .clearfix::after{
    content: '';
    clear: both;
    display: block;
    }
    
  • chrome 浏览器默认字体大小 16px,默认间距 8px

  • 一个元素的高度是由其内部 文档流 的高度总和决定的

  • 文档流就是文档内元素的流动方向

    • 内联元素从左往右流动,如果流动遇到阻碍则换行继续,从左向右流动

    • 块级元素,每一个块级元素独占一行,从上往下流动

    • CSS 属性值 word-break:break-all, 可以将单词打断点,会把整个词分开断点,如下代码预览:

    https://jsbin.com/ketaxum/2/edit?html,css,output

    • CSS float:left; positon:fixed; position:absolute 都能使元素脱离文档流
  • 为什么内联元素中间会有一个空格的距离,因为内联元素之间如果有换行符或者空格存在,浏览器会解析为一个空格

  • 每一个字体都有一个建议行高,默认的 line-heigth 由字体设计师决定

  • CSS 中 width 的默认值是 auto

  • box-sizing:content-boxwidth 不包含 paddingborder,元素默认

  • box-sizing:border-boxwidth 包含 paddingborder

  • 在布局时,尽量不要给元素定义宽度和高度,会有很多不确定性,妙用 max-widthmin-width

CSS 经典布局方式

两栏布局

  • 方法一:浮动布局

    <div class="aside"></div>
    <div class="main"></div>
    
    div {
    height: 500px;
    }
    .aside {
    width: 300px;
    background-color: #f60;
    float: left;
    }
    .main {
    background-color: green;
    margin-left: 300px;
    }
    

左侧栏固定宽度向左浮动,右侧主要内容用 margin-left 留出左侧栏的宽度,默认宽度是auto, 自动填满剩下宽度 demo

右侧固定宽度,左侧自适应则是同理,只要将固定栏右浮动,使用 margin-right 即可,

  div {
    height: 500px;
  }
  .aside {
    width: 300px;
    background-color: #f60;
    float: right;
  }
  .main {
    background-color: green;
    margin-right: 300px;
  }
  • 方法二:浮动布局 + 负外边距

    <div class="clearfix">
    <div class="aside">
    </div>
    <div class="main">
      <div class="content"></div>
    </div>
    </div>
    
    .clearfix::after {
    content: '';
    display: block;
    clear: both;
    }
    div {
    height: 500px;
    }
    .aside {
    width: 300px;
    float: left;
    margin-right: -100%;
    background-color: #f60;
    }
    .main {
    width: 100%;
    float: left;
    }
    .main .content {
    background-color: green;
    margin-left: 300px;
    }
    

左侧固定栏指定一个右侧的100%的负边距,为整个屏幕的宽度,这就使得main的最左侧与屏幕的最左侧对齐,此时的main的宽度是100%,因此需要其子内容content指定一个左侧的外边距空出左侧栏的位置,即左侧栏的宽度300px;适应一侧宽度为100%的布局 demo

  • 方法三:绝对定位

    <div class="box">
    <div class="aside">
    </div>
    <div class="main">
    </div>
    </div>
    
    body {
    margin: 0;
    }
    div {
    height: 500px;
    }
    .aside {
    width: 300px;
    position: absolute;
    left: 0;
    top: 0;
    background-color: #f60;
    }
    .main {
    background-color: green;
    margin-left: 300px;
    }
    

采用绝对定位,根据绝对定位脱离文档流的特性,demo

  • 方法四: flex 布局

    <div class="cainter">
    <div class="aside"></div>
    <div class="main"></div>
    </div>
    
    div {
    height: 500px;
    }
    .cainter {
    display: flex;
    }
    .aside {
    flex: 0 0 300px;
    background-color: #f60;
    }
    .main {
    flex: 1 1;
    background-color: green;
    }
    

弹性盒模型的方式是最简单的,如果不考虑浏览器兼容性的话,则可以使用此方法 demo

三栏布局(左中右)

三栏布局的特点:两边定宽,然后中间的 widthauto, 可以自适应内容

  • 方法一:用绝对定位的方法

原理则是,左侧和右侧布局用绝对定位分别定位在左侧和右侧,中间的布局则用 margin-leftmargin-right 空出左右栏位置来,demo

<div class="cainter">
  <div class="left"></div>
  <div class="center"></div>
  <div class="right"></div>
</div>
div {
  height: 500px;
}
.cainter {
  position: relative;
}
.left {
  position: absolute;
  top: 0;
  left: 0;
  width: 100px;
  background: red;
}
.right {
  position: absolute;
  top: 0;
  right: 0;
  width: 100px;
  background: green;
}
.center {
  background: yellow;
  margin-left: 100px;
  margin-right: 100px;
}

由于采用了绝对定位,所以在布局上三者的位置可以随意更换;

  • 方法二 使用 float 属性

左右两栏使用 float 属性,中间栏使用 margin 属性撑开;demo

  <div class="cainter clearfix">
    <div class="left"></div>
    <div class="right"></div>
    <div class="center"></div>
  </div>
  .clearfix::after {
    content: '';
    display: block;
    clear: both;
  }
  div {
    height: 500px;
  }
  .cainter {
    position: relative;
  }
  .left {
    width: 100px;
    background: red;
    float: left;
  }
  .right {
    width: 100px;
    background: green;
    float: right;
  }
  .center {
    background: yellow;
    margin-left: 100px;
    margin-right: 100px;
  }

缺点:1. 当宽度小于左右两边宽度之和时,右侧栏会被挤下去;2. html结构不正确

  • 方法三,浮动 + 负外边距 (双飞翼布局)

    • 三栏都采用左浮动
    • 中间栏也是左浮动,默认情况下由于前面中间栏 占据了 100% 的宽度,因此左侧是在另起一行显示,为左侧栏设置 margin-left: -100%; 即整个屏幕的宽度100%,这就令左侧栏布局到中间栏的最左侧
    • 右侧栏也是左浮动,此时默认的情况下也是在中间栏的下一行,同样利用 margin-left: -300px; 300px 为右侧模块宽度,使其到上一行最右侧位置
    • 中间栏内容部分则需要利用分别等于左右栏宽度外边距来空出它们的位置

      <div class="cainter clearfix">
      <div class="center">
      <div class="main"></div>
      </div>
      <div class="left"></div>
      <div class="right"></div>
      </div>
      
      .clearfix::after {
      content: '';
      display: block;
      clear: both;
      }
      div {
      height: 500px;
      }
      .cainter {
      position: relative;
      }
      .center {
      float: left;
      width: 100%;
      background: yellow;
      }
      .left {
      float: left;
      width: 200px;
      margin-left: -100%;
      background: green;
      }
      .right {
      float: left;
      width: 300px;
      background: red;
      margin-left: -300px;
      }
      .main {
      margin-left: 200px;
      margin-right: 300px;
      }
        
      

这种方法的好处就是主体内容可以在前面优先加载;缺点:结构不正确,且多了一层标签 demo

  • 方法四: flex布局

    <div class="container">
    <div class="left"></div>
    <div class="middle"></div>
    <div class="right"></div>
    </div>
      
    
    div {
    height: 500px;
    }
    .container {
    width: 100%;
    display: flex;
    }
      
    .left {
    width: 100px;
    background: green;
    }
    .middle {
    width: 100%;
    background: yellow;
    }
    .right {
    width: 100px;
    background: red;
    }
      
    

不考虑兼容性的话,最靠谱的一种方式 demo

CSS 垂直居中,水平居中方式

一、水平居中

1. 行内元素水平居中

text-align:center; 可以实现块级元素内部的行内元素的的水平居中,此方法只对 display:inline-block display:inlie; display:inline-table 和 display:inline-flex 元素水平居中有效,并且是给父级设置样式:

.parent {
  text-align: center;
}

小技巧:如果是一个块级元素,我们可以先改变为 display:inline-block; 就可以使用 text-align:center;

2. 块级元素的水平居中

  • 将该元素的左右外边距设置为 auto , 此方法必须是块级元素有宽度才可以,否则不起作用;

    .box {
    width: 100px; // 宽度属性是必须的
    margin: 0 auto;
    }
    
  • 使用 table + margin 先将子元素设置为块级表格显示,再将其居中,display:table 在表现上类似 block 元素,但是宽度为内容宽;

    <div class="parent">
    <div class="child">Demo</div>
    </div>
    <style>
      .parent {
          border: 1px solid #ddd;
          height: 100px;
      }
      .child {
          display: table;
          margin: 0 auto;
          background: red;
      }
    </style>
      
    
  • 使用 absolute + transform 先将父元素设置为相对定位,然后子元素设置为绝对定位,left 值设置为 50% , 然后通过移动子元素的一半宽度即可

    <div class="parent">
    <div class="child">Demo</div>
    </div>
    <style>
      .parent {
          border: 1px solid #ddd;
          height: 100px;
          position: relative;
      }
      .child {
          position: absolute;
          left: 50%;
          transform: translateX(-50%);
      }
    </style>
    

transform 属于 css3 内容,存在兼容性问题,高版本浏览器需加上前缀

  • 使用 flex + justify-content 给父级加

    <div class="parent">
    <div class="child">Demo</div>
    </div>
    <style>
    	.parent {
      display: flex;
      justify-content: center;
    }
    </style>
    
  • 使用flex+margin,通过flex将父容器设置为 flex 布局,再设置子元素居中

    <div class="parent">
    <div class="child">Demo</div>
    </div>
    <style>
      .parent {
          display: flex;
      }
      .child {
          margin: 0 auto;
      }
    </style>
      
    

3. 多块级元素水平居中

  • 利用弹性布局(flex),实现水平居中,其中 justify-content 用于设置弹性盒模型子元素在主轴(默认横屏)方向上的对齐方式,

    <div class="parent">
    <div class="child">demo1</div>
    <div class="child">demo2</div>
    <div class="child">demo3</div>
    </div>
    <style>
      .parent {
          border: 1px solid #ddd;
          height: 100px;
          display: flex;
          justify-content: center;
      }
      .child {
          background: red;
          padding: 10px;
          margin: 10px;
      }
    </style>
      
    

demo

  • 利用inline-block ,子级全部设置为 display:inline-block; 父级设置 text-align:center;

    <div class="parent">
    <div class="child">demo1</div>
    <div class="child">demo2</div>
    <div class="child">demo3</div>
    </div>
    <style>
      .parent {
          border: 1px solid #ddd;
          height: 100px;
          text-align: center;
      }
      .child {
          background: red;
          padding: 10px;
          margin: 10px;
          display: inline-block;
      }
    </style>
      
    

demo

4. 浮动元素水平居中

  • 定宽的浮动元素,通过设置子元素 relative + 负margin,原理如图:

gitHub

demo 注意:样式设置在浮动元素的本身

  • 不定宽的浮动元素,原理如图:

demo

  • 通用办法 flex 布局

    <div class="parent">
    <span class="chlid">水平居中</span>
    </div>
    <style>
    	.parent {
          display:flex;
          justify-content:center;
      }
      .chlid{
          float: left;
          width: 200px;// 有无宽度不影响居中
      }
    </style>
    

5. 绝对定位元素水平居中

通过子元素绝对定位,加上 marging:0 auto 实现;

demo

垂直居中

1. 单行内联元素重置居中

<div class="box">
  <span>单行文本元素垂直居中</span>
</div>
<style>
    .box {
        height: 100px;
        line-height: 100px;
        border: 1px solid #ddd;
    }
</style>

2. 多行内联元素垂直居中

  • 利用 flex 布局,实现垂直居中,其中 flex-direction: column; 定义主轴方向为纵向

    <div class="parent">
    <p>多行文本实现居中,多行文本实现居中,多行文本实现居中,多行文本实现居中,    
      多行文本实现居中,多行文本实现居中,多行文本实现居中,多行文本实现居中,    
      多行文本实现居中,多行文本实现居中,多行文本实现居中,多行文本实现居中</p>
    </div>
    <style>
    .parent { 
      height: 140px;
      display: flex;
      flex-direction: column;
      justify-content: center;
      border: 2px solid #ddd;
    }
    </style>
      
    

demo

  • 利用表格布局, vertical-align: middle 可以实现子元素的垂直居中

    <div class="parent"> 
    	<p>多行文本实现居中,多行文本实现居中,多行文本实现居中,多行文本实现居中,    
      多行文本实现居中,多行文本实现居中,多行文本实现居中,多行文本实现居中,    
      多行文本实现居中,多行文本实现居中,多行文本实现居中,多行文本实现居中</p>
    </div>
    <style>
    .parent { 
      height: 140px;
      border: 2px solid #ddd;
      display: table;
    }
    .child {
      display: table-cell;
      vertical-align: middle;
    }
    </style>
    

3. 块级元素垂直居中

  • 使用 absolute + 负 maring 前提是已知模块的宽度和高度, 与绝对定位的水平居中遥相呼应,是平时用的多的布局方式;

    <div class="parent">
      <div class="child">固定高度的块级元素垂直居中。</div>
    </div>
    <style>
    	.parent {
          position: relative;
      }
      .child {
          position: absolute;
          top: 50%;
          height: 100px;
          margin-top: -50px;
      }
    </style>
    
  • 使用 absolute + transform 此方法适用于高度和宽度未知时

    <div class="parent">
      <div class="child">固定高度的块级元素垂直居中。</div>
    </div>
    <style>
    	.parent {
          position: relative;
      }
      .child {
          position: absolute;
          top: 50%;
          transform: translateY(-50%);
      }
    </style>
      
    
  • 使用 flex + alig-items 与做水平居中的 flex + justify-content:center; 对应,是目前布局经常用的,有兼容性问题;

    <div class="parent">
     <div class="child">未知高度的块级元素垂直居中。</div>
    </div>
    <style>
    .parent {
     display:flex;
     align-items:center;
    }
    </style>
      
    

三、水平垂直居中

常用的适合没有兼容问题或者没有定宽高的布局

方法1:绝对定位与负边距实现 (已知宽高)

<div id='container'>
  <div id='center' style="width: 100px;height: 100px;background-color: #666">center</div>
</div>
<style>
  #container {
    position: relative;
  }
  #center {
    position: absolute;
    top: 50%;
    left: 50%;
    margin: -50px 0 0 -50px;
  }
</style>

方法2: 绝对定位与 margin:auto (已知宽高)

<div id='container'>
  <div id='center' style="width: 100px;height: 100px;background-color: #666">center</div>
</div>
<style>
  #container {
    position: relative;
  }
  #center {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    margin: auto; // 此处是重要写法
  }
</style>

方法3: 绝对定位 + CSS3 (未知宽高) 不考虑兼容性的话 此方法非常舒服

<div id='container'>
  <div id='center' style="background-color: #666">center</div>
</div>
<style>
  #container {
    position: relative;
  }
  #center {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate3d(-50%, -50%, 0);
  }
</style>

方法4: flex 布局 移动端常用,pc不考虑兼容可用

<div id='container'>
  <div id='center' style="width: 100px;height: 100px;background-color: #666">center</div>
</div>
<style>
  #container {
    height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
  }
</style>

后记

这篇总结也是站在一些前辈(大神)的基础上总结的一些技巧、方法,他们的文章教会了我很多,学到了很多!希望以后可以达到他们所在的成就,加油吧!持续不断的学习(折腾!!!)
CSS 的学习是由易到难,越往后学,越觉得CSS的难点所在,所以不管是在平时的工作中还是在自己折腾的项目中都是需要重视CSS的书写,多多的尝试一些新的CSS属性以及更多的CSS布局,多多的总结吧!

参考文章

如何居中一个元素(终结版)

CSS 两栏布局,三栏布局

CSS 布局说