CSS:Margin与布局

Margin与宽高度的关系

博客同步地址Margin与布局css

在讲此以前,必须知道什么是containing-box以及一些宽高度的一些关系,关于containing-box的概念以及与宽高度的关系可看个人前一篇文章CSS:关于元素高度与宽度的讨论 系列文章(三)html

1.元素containing-box宽高度等于内容宽度(原理1)

HTMLgit

<div class="wrap">
    <div class="item1"></div>
    <div class="item2"></div>
</div>

CSSgithub

.wrap {
    float: left;
    border: 2px solid #000;
  }
 .item1 {
    width: 100px;
    height: 100px;
    background: #fdf;
    margin-left: 10px;
    margin-top: 10px;
    margin-right: 20px;
    margin-bottom: 30px;
 }
.item2 {
    width: 50px;
    height: 50px;
    background: #adf;
 }

图片描述
能知足原理1的条件只有一种,元素不设宽度且不在文档流中,此时,父元素wrap产生的containing-box的宽高宽度等子元素border-box的宽高度加上外边距的宽高度,也就是说,子元素的margin值也是其containing-box的一部分。margin一共有两类参考线,第一类是margin-top与margin-left的参考线,第二类是margin-bottom与margin-right的参考线,第一类margin的参考线是以其所处的containing-box的边缘线为参考线,如上例所示,当调整元素.item1的margin-top与margin-left的值时,元素.item1所处的containing-box的大小也在发生变化所以其边缘线也在不断变化同时也就致使.item1元素自身的位置也在发生变化,看起来就是.item1自身发生了移动。第二类margin的参考线是以元素自身的边缘线(外边距的外侧为边缘线)为参考线,一样的,调整上例中的margin-bottom值,.item1的margin-bottom也在不断的发生变化,也就是说其自身边缘线在不断的移动,同时致使了.item2的移动。根据上面的论述,咱们能够得出结论,外边距的调整也就等于让其自身相对的参考线的位置在发生移动,同时致使相对于参考线运动的元素发生移动。元素自身相对于containing-box的边缘线移动而移动,与元素自身为兄弟关系的元素相对于元素自身的边缘线移动而移动。参考线示意图如图所示,按箭头所指方向使参考线变化的margin值都为正值。
综上,咱们能够利用margin对元素自身进行移动,同时也可以让其相邻元素进行移动,移动的同时咱们须要知道的是其所处的containing-box的大小也在发生变化。
图片描述
综上,当元素宽高度等于内容宽高度时,可经过调整内容的margin值来调整其containing-box的大小,由于containing-box的变化也就会致使元素自己的移动,也就是说既能够移动元素,也可调整元素与元素之间的间距。segmentfault

2.元素内容宽度等于其containing-box的宽度(原理2)

<div class="wrap">
   <div class="wrap-inner"></div>
</div>

.wrap {
    width: 100px;
    border: 2px solid #000;
    margin: 0 auto;
}
.wrap-inner {
    height: 50px;
    background: #fdf;
}

图片描述

上例中,元素wrap-inner的border-box宽度加上margin的大小等于其containing-box的宽度,所以当containing-box宽度固定,根据公式'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' = width of containing block,调整其自身margin-left或margin-right值,便会使wrap-inner自身大小发生变化,margin-left为正值且值逐渐变大,则wrap-inner自身宽度逐渐变小,若margin-left为负值且逐渐变小,则wrap-inner自身宽度逐渐变大,margin-right同理。必定要注意这里的宽度继承和width:100%是有本质区别的,由于width:100%就等于它的containing-box的100%和它的margin,border或者padding都木有关系,具体可看个人关于宽度与高度讨论的系列文章三里的例子,罗嗦了一点,可是这里是容易犯错误的地方。必定要注意,必定要注意,必定要注意!!!。重要的事情说三遍。浏览器

  • 将margin-left和right调整为-10px,如图,根据计算,wrap-inner变宽
    图片描述布局

  • 将margin-left和right调整为10px,如图,根据计算,wrap-inner变窄
    图片描述spa

综上,当元素宽或高度等于其containing-box的宽度或高度时,且containing-box的宽度固定咱们即可以利用margin对其进行自身宽度大小的调整。也就是说宽高度和containing-box有关系时,咱们利用margin可进行内里元素大小的调整。设计

利用Margin进行布局

一般在布局中咱们会遇到那些问题呢?下面是我本身实践中遇到的一些问题3d

问题1

当咱们拿到一份设计稿,而后这份设计稿有像下面这样的布局,总体居中,里面元素排一排,固然布局的方式会有不少种,那么若是咱们采用浮动布局或者display:inline-block进行布局会出现什么问题呢,如图咱们能够看出,若采用上述两种方式进行布局,那么每一个块的宽度加上间隙,就会超出包含块的宽度,固然咱们也能够将包含块的宽度进行增大以留下足够的位置供元素摆放,可是这种方法明显是不可取的,那么如何解决这个位置不够的问题呢,能够看下面的栗子1 。
图片描述
栗子
html

<div class="container">
  <div class="inner-wrap">
      <div class="inner"></div>
      <div class="inner"></div>
      <div class="inner"></div>
  </div>
</div>

css

body {
  margin: 0;
}
.container {
  margin: 0 auto;
  width: 980px;
}
.inner-wrap {
  margin-left: -10px;
}
.inner {
  float: left;
  margin-left: 10px;
  width: 320px;
  height: 200px;
  background: #2df;
}

此布局便利用了原理2,利用负margin增长了inner-wrap的宽度,但不改变总体的宽的状况下,实现效果。以下
图片描述

问题2

上面的例子仅仅只是实现了三列固定宽度的布局,这样的布局当屏幕宽度发生变化的时候便会出现问题。所以咱们便会有以下需求。

左右列固定,中间列自适应

栗子
html

<div class="main">
  <div class="main-content"></div>
</div>
<div class="left"></div>
<div class="right"></div>

css

.main {
  float: left;
  width: 100%;
}

.main-content {
  height: 200px;
  background: #2da;
  margin: 0 200px;
}

.left,.right {
  float: left;
  width: 200px;
  height: 200px;
  background: #ccc;
}

.left {
  margin-left: -100%;
}

.right {
  margin-left: -200px;
}

效果以下,当你缩小屏幕时,中间部分会随着屏幕的缩小而缩小,另外两部分宽度不变,一样也知足了主要内容优先加载的需求,可谓一箭双雕
图片描述

分析

能够看出上面的布局利用了原理2,可是这里仍然会有几个为何要问。

  • 首先,为何main里面必定要嵌套main-content,为何不能直接使用单个main(假设1)?

  • 其次,为何main上必定要设置float:left,能够设置其余值吗,如position:absolute(假设2)?

分析上面的布局以前,咱们也要了解到上面的布局知足了咱们的什么需求,这里有两点1.主要内容优先加载。2.主要内容自适应。这里咱们能够分析一下,咱们是怎样达到上述两个目的的。首先,要达到目的1,咱们就的把div.main放在前面来写,由于浏览器是从下到下渲染页面的,放在前面的也就会先渲染。且因为div.main为文档流中的块级元素,所以会独占一行,所以咱们须要使其脱离文档流,这样才能使下面的元素能有机会上的来(这里之因此不考虑display:inline-block是由于div.main的长度会独占一行,就算设置display:inline-block也没有任何做用,下面的元素仍然上不来)。而要达到目的2,须要用到原理2。同时在上面提出的两个问题中,有两个假设。

假设1,若是使用单个main可不能够知足上述两个需求?咱们能够试试。
html

<div class="main"></div>
<div class="left"></div>
<div class="right"></div>

css

body {
  margin:0;
}
/*这里注意须要改掉main的流方式,下面的元素才上的来*/
.main {
  float:left
  margin: 0 210px;
  height: 200px;
  background:#2da;
}
.left,.right {
  float: left;
  width: 200px;
  height: 200px;
  background: #ccc;
}
.left {
  margin-left: -100%;
}
.right {
  margin-left: -200px;
}

图片描述
从中线分开的黄色两部分为各自为main的左右外边距

从结果中,咱们能够看出使用单个main是不行的,由于在不设宽度且元素不在文档流中时,元素的宽度为0,不能知足咱们的需求,正由于咱们同时要知足1.main元素不在文档流中2.元素不设宽度且在文档流中。这两个条件固然是不能同时在一个main元素下能达到的,所以咱们须要再嵌套一个main-content让它来知足条件2。这也就解释了为何必定要嵌套一个main-content。
解决了问题1,如今咱们来讲问题2。

假设2,main上的float值能够换为position:absolute吗?
一样的,咱们试试
html

<div class="main">
  <div class="main-content"></div>
</div>
<div class="left"></div>
<div class="right"></div>

css

body {
  margin: 0;
}
.main {
  position:absolute;
  width:100%;
}
.main-content {
  margin: 0 210px;
  height: 200px;
  background: #2da;
}
.left,.right {
  width: 200px;
  height: 200px;
  background:#ccc;
}
.left {
  float: left;
}
.right {
  float: right;
}

答案是能够的,只是咱们须要改掉一些值,而当main为float之因此要给div.leftdiv.right要设置margin-left值是由于浮动元素浮动时,当它的外边缘碰到包含框或者另外一个浮动框的边框为止。而为浮动元素的div.main占据了整整一行,所以下面的浮动元素div.leftdiv.right便被挤了下来,而设置它们的margin-left值即可以把它们移上去,这里便运用了原理1。而当咱们把div.main的float值改成position:absolute时,便不会存在被挤下来的问题,可直接设置div.leftdiv.right的float的值。效果以下。
图片描述
如若只须要达到宽度自适应的要求,那么,这时候即可以将div.main放在最后面且不用嵌套div.main-content,具体如何实现,你们能够本身试试。
两列布局的道理也是差很少的,这里我就不写了,你们能够看这篇文章
margin系列之布局篇

问题3

以下所示设计稿,在咱们进行布局的过程当中,可能会出现border重合的状况,由于一方面咱们须要对整个总体加上border,而另外一方面咱们又须要利用border隔开那三个小块。那么若是咱们对每一个小块都加上右边框,能够想象,最右边就会出现边框的堆叠而这不是咱们但愿看到的,因此,要如何解决这个问题,能够看以下例子给出的答案。
图片描述
栗子
html

<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
</ul>

css

ul {
  position:absolute;
  margin: 0;
  padding:0;
  list-style:none;
  border: 4px solid #c5c5c5;
}
li {
  float:left;
  width: 200px;
  height: 50px;
  line-height: 50px;
  text-align: center;
  border-right: 4px solid #c5c5c5;
}

没在li上加margin-right:-4px;前,效果如图,发生了堆叠。
图片描述
加了margin-right: -4px后,达到预期效果。由于加上了ul的右边框发生了移动与第三个li的右边框进行了重叠。所以效果上来看便符合了预期,如图
图片描述
此布局便利用了原理1,经过元素对相邻元素位置的控制来达到预期的效果。
而利用原理1也能够实现元素居中的布局,先让元素上左各移50%,而后再让设置元素的上左margin值设置为元素自身宽度的一半长度,以对元素自己进行移动。即可达到元素居中放置的目的。

总结

1.元素宽度等于containing-box宽度时。能够经过调整margin的值来调整元素的宽度。2.元素宽度与containing-box无关时。能够经过调整margin的值来移动元素的位置。

相关文章
相关标签/搜索