css 应用之 - margin的妙用

margin 实现居中

在限定盒子宽度的前提下.

<style>
    .conatiner{}
    .inner{
        width:100px;
        height:100px;
        background:orange;
        margin-left:auto;
        margin-right:auto;
    }
</style>

<div class="container">
    <div class="inner"></div>
</div>
margin 正值

块级元素, 如果不设置宽度, 再加上 margin 正值的话, margin 则会自动压缩盒子的宽;
常用于自适应布局, 两边始终保持左右的 margin 值, 中间内容宽度根据屏幕宽度不同自适应

<style>
  *{
    margin:0;
    padding:0;
  }
  .container{
    background: pink;
    height: 30px;
  }
  .inner{
    height: 30px;
    margin-left: 20px;
    margin-right: 20px;
    background: orange;
  }
</style>

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

这里写图片描述

margin 负值
  • 边框重叠
 <style>
   * {
     margin: 0;
     padding: 0;
   }
   .container{
     background:skyblue;
     overflow: hidden;
   }
  ul {
     float: left;
     margin-left: 20px;
     background: red;
   }

   li {
     list-style: none;
     width: 100px;
     height: 100px;
     background: pink;
     border: 10px solid orange;
   }

   .merge-border li {
     margin-bottom: -10px;
   }
 </style>

<div class="container">
   <ul>
     <li></li>
     <li></li>
   </ul>

   <ul class="merge-border">
     <li></li>
     <li></li>
   </ul>
 </div>

这里写图片描述

  • 横向拉升父容器宽度, 实现等距分列

比如四列, 想让左右两端对齐父容器两边界, 然后每个容器间的间距相等, 而且能够自适应屏幕宽度.
常规操作为, 子元素浮动布局, 靠左, 然后每个子元素添加 margin-right , 然后一排最后一个元素的 margin-right 为 0 ;
利用负 margin , 则可以先拉长父容器的长度一个间距宽 , 然后再每个元素取 25% ( 4 列为例子 ) 排布 , 然后每个元素子内容, 不定宽度, margin-left 间距. 即可.
比如容器共宽 400px , 间距为20px , 则每一个元素宽应该为 (400-20*3) /4 = 85px 宽
现在先拉长 20px 宽, 容器宽为 420 px , 再平分4块, 每块为 105宽, 再内层 margin-left 20px , 则每块为 105-20 = 85px , 而容器往左负的距离, 也被第一个元素的内层 margin-left:20px 给拉回原位, 完美.

<style>
  *{
    margin:0;
    padding:0;
  }
  .list{
    margin-left: -18px;
    margin-right: 0;
  }
  .list li{
    width:25%;
    height: 100px;
    float:left;
    list-style: none;
  }
  .list .inner{
    height: 100px;
    margin-left: 18px;
    background: orange;
  }
</style>

<div class="container">
  <ul class="list">
    <li>
      <div class="inner"></div>
    </li>
    <li>
      <div class="inner"></div>
    </li>
    <li>
      <div class="inner"></div>
    </li>
    <li>
      <div class="inner"></div>
    </li>
  </ul>
</div>

效果如下:
这里写图片描述

这里最左边的一个元素 , 肯定是有一部分在可视区域范围之外的 , 也就是 间距宽的范围, 但是 innermargin-left 间距 , 则内容区域又回到可是范围.
1: 自适应
2: 改成其他列数方便, 如需要5列, 只需要设置 li 的宽度为 20% ;
3: 需改间距; 需修改 listmargin-left 的值和 li .innermargin-left 值.

分列布局: 左右固定中间自适应布局
  • 分列布局之 - float 定位
<style>
.container{
    overflow:hidden;
}
.left{
    width:100px;
    float:left;
    background:orange;
    height: 300px;
}
.main{
    margin:0 100px;
    background:pink;
    height: 80px;
}
.right{
    width:100px;
    float:right;
    background:skyblue;
    height: 300px;
}
 .footer{
    background: gray;
    height: 30px;;
  }
</style>
<div class="container">
    <div class="left">left</div>
    <div class="right">right</div>
    <div class="main">main</div>
</div>
<footer class="footer">footer</footer>

之所以可以实现的原理是: leftright 都是浮动元素,所以不占文档流空间,main 就直接从 container 0 0 的位置排布.
这里 mian 的高度比两侧小的时候, 也能撑开 container 的高度 , 而且这里的 main 元素必须在 leftright 后面

效果如下:

这里写图片描述

考虑到优先渲染主要内容 main 区域内容, 所以 main 放最前面 , 以下几种布局方式都能实现.

  • 分列布局之 - position 定位
<style>
    .container {
      position: relative;
    }
    .left {
      position: absolute;
      left: 0;
      top: 0;
      width:100px;
      background: orange;
      height: 300px;
    }
    .main {
      margin: 0 100px;
      height: 80px;
      background: pink;
    }
    .right {
      position: absolute;
      top: 0;
      right: 0;
      width:100px;
      background: skyblue;
      height: 300px;
    }
    .footer{
      background: gray;
      height: 30px;;
    }
</style>

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

效果如下

这里写图片描述

可以看出, 虽然能够实现左中右三列布局 , 但是 left 和 right 是撑不开父容器 `container 的高度的

  • 分列布局之 - 圣杯和双飞翼

圣杯布局和双飞翼, 在于处理 main 的内容区域的处理方式不一样

主要利用 浮动布局 + 负的 margin 的使用.
优先 main 标签 , main 独占一行, leftright 则会掉下来, 另起一行, 利用负的 margin , 将掉下来的 leftright 又挤到上一行, 也就是 main 的上面.
注意: main 也必须是浮动布局, leftright 的负 margin 才能挤上去.

step1 . 先实现分三列布局

<style>
  .container{
    overflow: hidden;
  }
  .main{
    background: pink;
    float:left;
    width:100%;
    height: 80px;

  }
  .left{
    float: left;
    width: 100px;
    background: orange;
    height: 300px;
    margin-left: -100%;
  }
  .right{
    float: left;
    width:100px;
    background: skyblue;
    height: 300px;
    margin-left: -100px;
  }
  .footer{
    background: gray;
    height: 30px;
  }
</style>

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

效果如下:

这里写图片描述

可以看出, 分列是实现了, 但是main 的内容区域却与 left 和 right 重叠了

step2. 实现 main 的内容正常显示 ,也就是要空开 left 和 right 的位置.

  • 圣杯实现

核心是先将 container 左右各压缩 leftright 的宽度. main 100% 的宽度也就刚好, 是它本该的显示区域, 然后 left 在上移后再往左移动自身宽度 , right 在上移后往右移动自身宽度. 即可.

以下仅展示在 step1 后添加的内容:

<style>
.container{
    padding:0 100px;
}
.left{
    position:relative;
    left:-100px;
}
.right{
    position:relative;
    right:-100px;
}
</style>

或者利用 box-sizing 属性, padding 为设置的盒子( main )宽度的一部分

.main{
    box-sizing:border-box;
    padding:0 100px;
}
  • 双飞翼实现

双飞翼布局, 主要是在不兼容 box-sizing:border-box; 的兼容. 当不设置一个块级元素的宽度时 , 给该块级元素设置 margin , 就可以使得该块级元素根据父元素的宽度和 margin 定义自身宽度.

<style>
    /* 其他的和 step1 的样式一致  */
    .inner{
        margin:0 100px;
    }
<style>

<div class="container">
  <div class="main">
    <div class="inner">inner</div>
  </div>
  <div class="left">left</div>
  <div class="right">right</div>
</div>
<footer class="footer">footer</footer>

效果如下:

这里写图片描述

分列布局之 - flex 实现
<style>
.container{
    display:flex;
}
.left{
    order:-1;
    flex-basis:100px;
}
.main{
    flex-grow:1;
}
.right{
    flex-basis:100px;
}

</style>

<div class="container">
    <div class="main">main</div>
    <div class="left">left</div>
    <div class="right">right</div>
</div>
相关

猜你喜欢

转载自blog.csdn.net/haokur/article/details/80520452
今日推荐