CSS-LAYOUT

掌握 css 布局需要掌握的基本规则和布局方式

Posted by 許敲敲 on June 19, 2020
  1. 一个元素总宽高为50px,要怎么在调整边框大小的时候,不需要重新计算和设置width/height呢?
  2. 为什么给一些元素设置宽高,但是却不生效?
  3. 如何将一个元素固定在页面的某个位置,具体怎么做?
  4. 为什么将某个元素z-index设置为9999999,但是它依然被其他元素遮挡住了呢?

页面布局的基本规则

  • 盒模型
  • 内联元素与块状元素
  • 文档流布局
  • 元素堆叠

盒模型

什么是盒模型?浏览器对文档进行布局的时候,会将每个元素都表示为这样一个盒子。

box

盒模型是根据元素的样式来进行计算的,我们可以通过调整元素的样式来改变盒模型。上图中的盒模型来自下面这个<div>元素,我们给这个元素设置了margin、padding和border:

<style>

  .box-model-sample {

    margin: 10px;

    padding: 10px;

    border: solid 2px #000;

  }

</style>

<div class="box-model-sample">this is a div</div>

  1. 盒模型会发生margin外边距叠加,叠加后的值会以最大边距为准。 需要注意的是,并不是所有情况下都会发生外边距叠加,比如行内框、浮动框或绝对定位框之间的外边距不会叠加。
<style>

  .box-model-sample {

    margin: 10px;

    padding: 10px;

    border: solid 2px #000;

  }

  .large-margin {

    margin: 20px;

  }

</style>

<div class="box-model-sample">这是一个div</div>

<div class="box-model-sample">这是另一个div</div>

<div class="box-model-sample large-margin">这是一个margin大一点的div</div>

margin-collapse

  1. 盒模型计算效果有多种,比如元素宽高是否包括了边框。我们可以通过box-sizing属性进行设置盒模型的计算方式,正常的盒模型默认值是content-box。使用box-sizing属性可以解决问题 1(调整元素的边框时,不影响元素的宽高),我们可以将元素的box-sizing属性设置为border-box
<style>

  .box-model-sample {

    height: 50px;

    margin: 10px;

    padding: 5px;

    border: solid 2px #000;

  }

  .border-box {

    box-sizing: border-box;

  }

</style>

<div class="box-model-sample">这是一个div(content-box)</div>

<div class="box-model-sample border-box">这是另一个div(border-box)</div>

对于默认content-box的元素来说,元素所占的总宽高为设置的元素宽高(width/height)等于:content + padding + border,因此这里该元素总高度为50 + 5 * 2 + 2 * 2 = 64px

内联元素与块状元素

盒模型可以解决我们如何精确控制元素大小问题, 但设置有时候会不生效, 这时候需要我们考虑 元素本身性质。

在浏览器中,元素可分为内联元素和块状元素。比如,<a>元素为内联元素,<div>元素为块状元素,我们分别给它们设置宽高示例页面

<style>
  a,

  div {

    width: 100px;

    height: 20px;

  }

</style>

<a>a-123</a><a>a-456</a><a>a-789</a>

<div>div-123</div>

<div>div-456</div>

<div>div-789</div>

效果:

inline-vs block

可以看到,<a>元素和<div>元素最主要的区别在于:

  • <a>元素(内联元素)可以和其他内联元素位于同一行,且宽高设置无效;

  • <div>元素(块状元素)不可和其他元素位于同一行,且宽高设置有效。

所以当我们给某个元素设置宽高不生效,是因为该元素为内联元素。那么有没有办法解决这个问题呢?

我们可以通过设置display的值来对元素进行调整。

设置为block块状元素,此时可以设置宽度width和高度height。

设置为inline内联元素,此时宽度高度不起作用。

设置为inline-block,可以理解为块状元素和内联元素的结合,布局规则包括:

  • 位于块状元素或者其他内联元素内;

  • 可容纳其他块状元素或内联元素;

  • 宽度高度起作用。

inline-block可以很方便解决一些问题:使元素居中、给inline元素(<a>/<span>)设置宽高、将多个块状元素放在一行等。

文档流和元素定位

如何将一个元素定位在页面某个位置 ?这个问题涉及文档流的布局和元素定位的样式设置。

什么是文档流呢?正常的文档流在 HTML 里面为从上到下,从左到右的排版布局。

文档流布局方式可以使用position样式进行调整,包括:

  • static(默认值)
  • inherit(继承父元素)
  • relative(相对定位)
  • absolute(相对非static父元素绝对定位)
  • fixed(相对浏览器窗口进行绝对定位)
  1. 元素position样式属性值为static(默认值)时,元素会忽略top/bottom/left/right或者z-index声明,比如我们给部分元素设置position: static的样式以及lefttop定位 :
a, p, div {

  border: solid 1px red;

}

.static {

  position: static;

  left: 100px;

  top: 100px;
}

postion static 示例页面我们可以看到给position: static的元素添加定位left: 100px; top: 100px;是无效的。

  1. 元素position样式属性值为relative时,元素会保持原有文档流,但相对本身的原始位置发生位移,且会占用空间,比如我们给部分元素设置position: relative样式以及lefttop定位:
a, p, div {

  border: solid 1px red;

}

.relative {

  position: relative;

  left: 100px;

  top: 100px;

}

postion relative 示例页面中,我们可以看到position: relative的元素相对于其正常位置进行定位,元素占有原本位置(文档流中占有的位置与其原本位置相同),因此下一个元素会排到该元素后方。

  1. 元素position样式属性值为absolute、且设置了定位(top/bottom/left/right)时,元素会脱离文档流,相对于其包含块(第一个postion 不为 static 的父级元素)来定位,且不占位。 postion absolute 示例页面

  2. 元素position样式属性值为fixed时,元素脱离文档流、且不占位,相对于相对于浏览器窗口进行定位。postion fixed 示例页面

元素堆叠 z-index

元素的堆叠方式和顺序,除了与position定位有关,也与z-index有关。通过设置z-index值,我们可以设置元素的堆叠顺序,比如我们给同级的元素添加z-index值:

z-index

z-index 示例页面 中,我们可以看到:

  • 当同级元素不设置z-index或者z-index相等时,后面的元素会叠在前面的元素上方;

  • 当同级元素z-index不同时,z-index大的元素会叠在z-index小的元素上方。

  • z-index样式属性比较常用于多个元素层级控制的时候,比如弹窗一般需要在最上层,就可以通过设置较大的z-index值来控制。

除了同级元素以外,z-index值的设置效果还会受到父元素的z-index值的影响。z-index值的设置只决定同一父元素中的同级子元素的(BFC)堆叠顺序。因此,即使将某个元素z-index设置为9999999,它依然可能因为父元素的z-index值小于其他父元素同级的元素,而导致该元素依然被其他元素遮挡。

总结

  1. 盒模型主要用来描述元素所占空间的内容;

  2. 一个元素属于内联元素还是块状元素,会影响它是否可以和其他元素位于同一行、宽高设置是否有效;

  3. 正常的文档流在 HTML 里面为从上到下、从左到右的排版布局,使用position属性可以使元素脱离正常的文档流;

  4. 使用z-index属性可以设置元素的堆叠顺序

拓展资料 布局方式

css flex:

  1. https://css-tricks.com/snippets/css/a-guide-to-flexbox/

  2. https://flexbox.help/