界面布局 - 基本规则

CSS 一个重点应用就是: 页面布局

页面布局就是:设置 网页元素 的位置、以及和周围的其他元素位置关系。

通俗的说,就是怎么摆放页面元素。

block 和 inline

元素的显示模式 分为: block (块模式) 和 inline (内联模式)

两种显示模式决定了元素不同的展示结果

不同的元素,有不同的默认显示模式,比如 p 默认就是 block模式, span 默认就是 inline模式

block模式 和 inline模式 最直观的差别是,前者会独占一行显示,后者尽量跟随前面的元素显示在一行中


  <p>块元素1</p>
  <span>内联元素1</span>
  <p>块元素2</p>
  <span>内联元素3</span>
  <span>内联元素4</span>
  <p>块元素3</p>


我们可以设置 css属性 display 的值为 block 或者 inline , 从而改变显示模式。


  <p>块元素1</p>
  <span>内联元素1</span>
  <p>块元素2</p>
  <span>内联元素3</span>
  <span>内联元素4</span>
  <p style='display:inline'>块元素3</p>

block 模式

如果一个元素 是 block 模式,显示特征如下:

  • 新开一行 显示该元素

    块级元素会 新开一行 显示,不管前面的元素是 内联元素 还是 块级元素。

  • 水平方向,占满它的父元素可用空间

    所以块级元素 通常会和上层元素一样宽

  • 垂直方向,占据的空间由其内容大小决定

  • 可以通过 css 属性 widthheight 设置该元素的宽和高

  • css 属性 paddingmarginborder 决定其他元素 和 该元素的间隔

缺省就是 block 模式的 元素有如下这些

address
article
aside
blockquote 
dd
div
dl
dt 
footer
form
h1 h2 h3 h4 h5 h6
header 
hr
li
main
nav
ol
p
pre
section
table
ul

另外,浏览器 缺省把 body 元素 也显示为 block

inline 模式

如果一个元素 是 inline 模式,显示特征如下:

  • 不会新开一行 显示该元素

    只要 当前行有剩余空间可以容纳自身内容,就会显示在里面。如果没有剩余空间,才会移到下一行。

    如果前面的兄弟元素是inline模式,往往会在同行显示

    如果前面的兄弟元素是block模式,则会在不同行显示

  • css 属性 width 、 height 不起作用

内联元素的大小就是其内容的大小,无法通过 width 、 height 属性进行设置

除非你通过修改display属性值为 block 或者 inline-block 改变其内联本质。

  • 垂直方向的 属性 padding、 margin 、 border 有效果,但是不能把其他的inline元素 隔开

  • 水平方向的 属性 padding、 margin 、 border 决定其他元素 和 该元素的间隔



缺省就是 inline 模式的 元素很多,常见的有

a
audio
b
br
button
canvas
em
embed
i
iframe
img
input
label
select
span
strong
svg
textarea
video

inline-block

inline-block 也是常用的display模式

通常用在 按钮 之类的方块状元素上

好处是,让这些元素既有inline的不换行的特征, 也可像block元素一样设置 width 、 height、margin、padding

比如


<head>
  <style>
    ul {
        list-style-type:none;
    }

    li { 
        display:inline-block;
        margin: 2em;   
        width: 150px;
        background-color: #755ac3;
        color: #fff;
        border-radius: 100px;
        text-align: center;
    }
  </style>
</head>

<body>
<ul class="wrapper"> 
  <li>自动化软件测试</li>
  <li>性能测试</li>
  <li>QT</li>
  <li>Django</li>
  <li>爬虫数据处理</li>
  <li>web前端开发</li>
</ul>

</body>

li 默认是 block 模式的, 如果不设置为 inline-block, 所有的元素都是单独一行, 就可能不符合设计者的要求。

包含块

浏览器呈现界面时,每个html 元素(不管是block模式还是inline模式)都对应一个 显示 方块区。

这个方块区 被称为 包含块 (containing block)

由内到外,这个包含块 区域可以分为四部分:

  • Content区

    也就是实际内容区

  • Padding 区

    又被称为 内边距 区

  • Border 区

    又被称为 边框 区

  • Margin 区

    又被称为 外边距 区


如下图所示

image


如果一个block元素,没有其它兄弟元素,它的 包含块 就是其 最近的 块级(非inline元素)上级元素 的 Content区。


初始包含块(initial containing block) ,范围是 整个浏览器 内容窗口区(viewport)

HTML文档中最上层的 html 标签元素 的包含块 就被包含在 初始包含块 里面,(范围小于初始包含块)

看一下这个例子

<!DOCTYPE html>
<html>

<head>
  <style>
  html {
    border: 5px dashed green;
  }

  body {
    border: 5px dashed red;
    margin : 20px

  }
  </style>
</head>

<body>  
    1
    <br>
    2
    <br>
    3 
</body>

</html>

可以发现 html 并没有占满所有的viewport高度。

因为html也是块级元素, 显示宽度是 上级viewport 的 整个宽度,高度却是由自身的内容决定的。

如果要让 html、body 占满所有的viewport高度,可以这样设置


  body {
    margin : 0;
    height: 100vh;

  }

100vh 就是 100% 的 viewport高度

宽度和高度

可以通过 widthheight 分别指定 block模式元素的 宽度高度

widthheight 的值可以是任何的长度单位,比如 10px, 1em,1rem,1vh 等等

比如

{
  width : 10px;
  height : 2em;
}

缺省情况下,widthheight 是设置元素 Content区 的宽度和高度

image

比如

<html>
<head>
  <style>
      
  #container {
    border : 1px solid blue;    
  }

  #target {
    border: 5px solid green;    
    width  : 200px;
    height : 100px;
    padding: 5px;
    margin: 8px;
  }

  </style>
</head>

<body>

  <div id='container'>    
    <div id='target'>      
    </div>
  </div>

</body>
</html>

你可以为该元素设置 box-sizing: border-box ,这样 width,height设置的就是 可见区 的 宽度和高度, 也就是Border区的外边缘

内间距 padding

padding 属性指定了元素 内边距 ,也就是 元素 border内边线元素自身content边界 之间的距离

padding 的值可以是任何的长度单位,比如 10px, 1em, 1rem 等等


指定 padding 的时候,包括 上、下、左、右 四个边的间距

可以用 padding-toppadding-bottompadding-leftpadding-right 分别指定 上、下、左、右 四个边的间距

比如

padding-top : 10px;

padding-bottom : 2em;

padding-left : 2rem;

padding-right : 20px;

也可以直接用 padding 一起指定,常见的有如下这些写法

  • padding: 10px

四个边的 padding 都是 10px

  • padding: 10px 20px

第1个参数 指定 上下 两个边的 padding,

第2个参数 指定 左右 两个边的 padding,

  • padding: 10px 20px 30px

第1个参数 指定 上边 的 padding,

第2个参数 指定 左右 两个边的 padding,

第3个参数 指定 下边 的 padding

  • padding: 10px 20px 30px 40px

第1个参数 指定 上边 的 padding,

第2个参数 指定 右边 的 padding,

第3个参数 指定 下边 的 padding,

第4个参数 指定 左边 的 padding


外间距 margin

margin 属性指定了元素的 外边距 ,也就是 元素 border外边线父元素content边界 之间的距离

margin 的值可以是任何的长度单位,比如 10px, 1em, 1rem 等等


指定margin的时候,包括 上、下、左、右 四个边的间距

可以用 margin-topmargin-bottommargin-leftmargin-right 分别指定 上、下、左、右 四个边的间距

比如

{
  margin-top : 10px;

  margin-bottom : 2em;

  margin-left : 2rem;

  margin-right : 20px;
}

也可以直接用 margin 一起指定,常见的有如下这些写法

  • margin: 10px

四个边的 margin 都是 10px

  • margin: 10px 20px

第1个参数 指定 上下 两个边的 margin,

第2个参数 指定 左右 两个边的 margin,

  • margin: 10px 20px 30px

第1个参数 指定 上边 的 margin,

第2个参数 指定 左右 两个边的 margin,

第3个参数 指定 下边 的 margin

  • margin: 10px 20px 30px 40px

第1个参数 指定 上边 的 margin,

第2个参数 指定 右边 的 margin,

第3个参数 指定 下边 的 margin,

第4个参数 指定 左边 的 margin


有些 HTML 元素有 预置的 非 0 margin 值 (比如: body, h1 - h6, p, fieldset, form, ul, ol, dl, dir, menu, blockquote dd).

body 缺省 margin 为 8px, 会导致 设置为 占满 浏览器窗口高度的 body 出现 垂直滚动条,

比如,下面的示例

<!DOCTYPE html>
<html>

<head>
  <style> 
  body{
    height:100vh;
  }
  
  div {
    height:100px;
    border:1px solid blue
  }
  </style>
</head>


<body>  
  <div>
    1
    <br>
    2
  </div>
</body>

</html>

可以,像这样把 margin改为 0

  <style> 
  body {
    height: 100vh;
    margin : 0;
  }
  </style> 

调试css

可以在浏览器DevTools 窗口中查看 元素的 宽、高、padding、margin 等等

还可以临时修改添加删除CSS属性,查看效果

详见视频讲解。

百分比

我们常常使用 百分比 指定 宽度、高度、 padding、margin

比如 width: 90%

这个百分比到底是谁 的 百分比呢?是 包含块

就是该元素 上级元素中 最贴近的块级 元素 的 Content区。

比如

<html>
<head>
  <style>
      
  #container {
    border : 1px solid blue;  
    width  : 200px;
    height : 400px;
  }

  #target {
    border: 1px solid green;  
    /* 包含块 宽度的 80% */
    width: 80% ;

    /* 包含块 高度的 60% */
    height: 60% ;

    /* 包含块 宽度 的 10% 20% */
    padding: 10% 20%;

    /* 包含块 宽度 的 5% 10% */
    margin: 5% 10%;
  }

  </style>
</head>

<body>

  <div id='container'>    
    <div id='target'>      
    </div>
  </div>

</body>
</html>

auto

我们经常会看到css设置 margin、padding、height、width 的值为 auto

比如

{
  margin: 5% auto;
  width: auto;
}

简单的说,auto 就是浏览器会自动选择一个合适的值。


width,height 的默认值(不指定)就是 auto

水平方向

水平方向的 auto 有种含义:占据尽量多的空间


看这个例子

<head>
  <style>
      
  #container {
    border : 1px solid blue;  
    height: 300px;
    width: 400px;
  }

  #target {
    border: 1px solid green;  
    margin: 5px;
    padding: 5px;
    /* width: auto; */
    height: 125px;
 }

  </style>
</head>

<body>
  <div id='container'>    

    <div id='target'>      
    </div>

  </div>
</body>

因为 target元素的 width 值没有指定, 缺省为 auto,

auto含义是占据尽量多的空间,所以水平方向贴满了包含块的可用长度(除了边框本身的宽度和margin)


再看一个例子

<html>
  <head>
    <style>
        
    #container {
      border : 1px solid blue;  
      height: 300px;
      width: 400px;
    }

    #target {
      border: 1px solid green;  
      margin-left: auto;
      width: 250px;
      height: 125px;
  }

    </style>
  </head>

  <body>
    <div id='container'>    
        
      <div id='target'>      
      </div>

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

margin-left: auto 让里面的target元素左边的margin占据尽可能多的空间,元素就靠右贴边了。

如果改为 margin-right: auto 让target元素右边的margin占据尽可能多的空间,元素就靠左贴边了。


如果改为 margin: auto , target元素左右margin同时尽可能的占据空间,就会各占一半

所以水平方向居中了,左右的margin各为 74px (要减去border本身1px )

垂直方向

垂直方向和 水平方向的规则不一样。

W3C规范指出:

如果 margin-topmargin-bottom 值 为 auto ,则它们的实际值为 0


前面的代码示例,如果改为 margin: auto , 那么 margin-topmargin-bottom 值 都为 auto ,则它们的实际值为 0

从浏览器开发者工具栏也可用看到 target 元素的 上下 margin都是0

由于排布元素的规律是从上到下,从左到右。 所以 target 元素 出现在上方


如果 height 的值为 auto , 就比较复杂了,

通常来说,是该元素自身的内容决定的。

如果元素本身内容为空,实际的高度为 0


看这个例子

<head>
  <style>
      
  #container {
    border : 1px solid blue;  
    height: 300px;
    width: 400px;
  }

  #target {
    border: 1px solid green;  
    margin: 5px;
    padding: 5px;
 }

  </style>
</head>

<body>
  <div id='container'>    

    <div id='target'>      
    </div>

  </div>
</body>

target元素 width、height都没有指定,都是缺省值 auto

水平方向占据了尽可能多的空间

而垂直方向,高度却是 0 ,因为它没有内容


如果给target 元素添加 一个 内部元素,比如

<head>
  <style>
      
  #container {
    border : 1px solid blue;  
    height: 300px;
    width: 400px;
  }

  #target {
    border: 1px solid green;  
    margin: 5px;
    padding: 5px;
 }

  </style>
</head>

<body>
  <div id='container'>    

    <div id='target'>   
        <p> sdfsdf  </p>
    </div>

  </div>
</body>

结果发现,target元素的高度,就是其内部 p元素的的高度

最大/最小 宽度高度

min-widthmax-widthmin-heightmax-height 分别用来指定元素的最小宽度、最大宽度、最小高度、最大高度

它们的优先级高于 widthheight 的优先级

<head>
  <style>

  .c-modal {
    margin: 2em auto;
    width:80%;
    min-width: 400px;
    max-width: 600px;
    padding: 1rem;
    background: #e2deed;
  }


  </style>
</head>

<body>

  <div class="c-modal"> 
    <p>
    hytest 是白月黑羽自己研发的自动化测试框架,
    
    它非常适合 做 系统测试 自动化, 
    
    而相比之下,pytest、unittest 更适合白盒的单元测试、集成测试。

    </p>
    它有如下优点:

    <p>
    上手非常简单 - 

    hytest 让大家直接用 Python 来写测试用例。

    如果你有 Python编程经验,1小时就可以上手,1天就可以灵活使用。

    </p>

    
    <p>
    操作直观易懂 - 测试用例以 目录文件结构存放,清晰明了

    </p>

    <p>
    初始化清除 清晰灵活 - 

    可以灵活地 挑选 要执行的测试用例

    </p>
    <p>
    漂亮的测试报告
    </p>
  
  </div>

</body>

可用发现,div.c-modal元素 受 min-widthmax-width的影响。

这样,随着窗口的缩放 不至于太长,也不至于太短,否则就会比较难看

可用对比去掉 min-widthmax-width 的效果


min-heightmax-height 在高度方面也是有同样的效果

背景色范围

设置一个元素的背景色,有效区域包括这个元素的 内容区、padding部分、border部分。也就是包含块除了margin部分

看这个例子

<!DOCTYPE html>
<html>

<body>  
  <p style='margin:20px;padding:20px;border: 5px dashed red;
    background:lightblue'>
    1
    <br>
    2
    <br>
    3 
  </p>
</body>

</html>

但是,如果背景色设置的是根元素 html ,背景色会占据 整个浏览器画布(canvas)。

如下:

<!DOCTYPE html>
<html  style='margin:20px;padding:20px;border: 10px dashed gray;background:lightblue'>

<body>  
  <p>
    1
    <br>
    2
    <br>
    3 
  </p>
</body>

</html>

而且如果html没有设置背景色,设置body的背景色会占据整个浏览器画布(canvas)

这样的规则是 W3C的规范 确定的



元素的背景色属性并不会传递给后代元素,

但是, 如果后代元素不重新设置背景色,后代元素背景色 也会显示为 最近设置背景色 上级元素的 颜色。

这是因为, 背景色的缺省值是 transparent 透明。