background背景图片自适应_一侧定宽、一侧自适应,尽量多的方案实现?「前端剑指offer」...

3164fc687487925eeb2b9bac807906c3.png

# 问题

一侧定宽、一侧自适应,尽量多的方案实现。

# 回答

有下面几种方案能实现一侧定宽一侧自适应。

  1. 使用flex布局,这也是目前主流方式。父容器设置display:flex,定宽字元素设置flex-basis或者width,自适应的子元素设置flex: 1,或者flex-grow: 1。
  2. 使用grid布局。父容器设置 display: grid,使用grid-template-rows 和 grid-template-columns 设置格子;子项使用grid-column 和 grid-row 设置在格子中的位置。 grid布局对浏览器的版本要求比较苛刻,IE基本不支持。
  3. 如果需要适配低端IE,可使用下面的传统的浮动布局。如果不但要适配低端IE,在布局时对DOM的结构顺序也有要求,比如对于侧边栏在左侧的布局希望自适应的元素DOM位置更靠前,则可以考虑使用圣杯布局或者双飞翼布局。
    1. 传统的浮动布局。定宽元素设置左浮动或者右浮动,自适应的元素响应的设置左margin或者右margin预留空间。需要注意的是为了避免父元素高度塌陷需要给父元素加清除浮动.clearfix::after{ content: ''; display: block; clear: both; }
    2. 圣杯布局。定宽元素和自适应元素都设置左浮,自适应元素设置宽度100%,定宽元素设置固定宽度,定宽元素因为DOM位置靠后会被挤下去。给定宽元素加上margin:-100%,此时定宽元素会上去和自适应元素的左侧重叠。给容器设置padding-left值为定宽元素宽度,给定宽元素设置position:relative,left设置负的自己的宽度。即可实现两栏布局。圣杯布局本质上利用了浮动和负margin的特性。但圣杯布局有个要求,就是自适应元素的宽度最小不能小于固定宽度侧边栏的宽度,否则就会出现错乱。
    3. 双飞翼布局。为了解决圣杯布局自适应元素宽度小于固定宽度侧边栏时样式出现错落的bug。原理是给自适应宽度内再多加一层div。定宽元素和自适应元素都设置左浮,自适应元素设置宽度100%,定宽元素设置固定宽度,定宽元素因为DOM位置靠后会被挤下去。给定宽元素加上margin:-100%,此时定宽元素会上去和自适应元素的左侧重叠。给自适应元素内的div加margin来规避重叠。

总结:圣杯布局和双飞翼布局都太老了,并且为了让自适应宽度DOM顺序靠前用了各自复杂操作既增加了代码的复杂度,也没有完美解决问题。推荐使用flex或者传统的两栏浮动方案。

# 解析

这种题目其实难在用口述的方式讲清楚这布局的使用方式,特别是老古董圣杯布局和双飞翼布局。当场动手写代码反而更友好。 不过不用过分担心自己的表达,面试官如果对这几种布局都很熟悉,你即使表达不清楚面试官也知道你是其实是会用的。如果面试官自己也仅仅熟悉一两种,你怎么回答都是对的。

flex两栏布局

<section>
  <main>main</main>
  <aside>aside</aside>
</section>

<style>
  section { 
    display: flex; 
  }
  aside { 
    width: 200px; 
    background: blue;
  }
  main { 
    flex-grow: 1; 
    order: 1; 
    background: red;
  }
</style>

https://codepen.io/jirengu/pen/rNMVdaL

grid 两栏布局

使用grid布局,先用grid-template-columns/grid-template-rows 给容器画虚拟格子,再把元素通过 grid-column/grid-row 塞到格子里。

<section>
  <main>main</main>
  <aside>aside</aside>
</section>

<style>
  section { 
    display: flex; 
  }
  aside { 
    width: 200px; 
    background: blue;
  }
  main { 
    flex-grow: 1; 
    order: 1; 
    background: red;
  }
</style>

https://codepen.io/jirengu/pen/PoGqRGV

传统浮动布局

老浏览器适用。需要注意的是浮动的侧边栏aside的DOM位置需要在自适应宽度的正常元素main的上方。

<section>
  <aside>aside</aside>
  <main>main</main>
</section>

<style>
  section::after { 
    content: '';
    display: block;
    clear: both;
  }
  aside { 
    float: left;
    width: 200px;
    background: red;
  }
  main {  
    margin-left: 200px;
    background: blue;
  }
</style>

圣杯布局

  • 特点:main在aside的DOM元素位置上方
  • 缺点:main的宽度不能小于aside
  • 演示:按照下方代码注释的step顺序,一行行复制并查看效果变化
<div class="section">
  <div class="main">main</div>
  <div class="aside">aside</div>
</div>

<style>
.section {
  padding-left: 100px;  /*step 4*/
  *zoom: 1;/*兼容IE6/7*/
}

.section:after {/*IE8不支持::*/
  content: '';
  display: block;
  clear: both;
}

.main {
  width: 100%;
  height: 80px;     /*step 1*/
  background: blue; /*step 1*/
}

.aside {
  width: 100px;     /*step 1*/
  background: red;  /*step 1*/
}

.main, .aside {
  float: left;      /*step 2*/
}

.aside {
  margin-left: -100%;  /*step 3*/
  position: relative;  /*step 5*/
  left: -100px;        /*step 5*/
}
</style>

https://codepen.io/jirengu/pen/vYXORdQ

双飞翼布局

  • 特点:main在aside的DOM元素位置上方
  • 缺点:main 里面还得加一层wrap
  • 演示:按照下方代码注释的step顺序,一行行复制并查看效果变化
<div class="section">
  <div class="main">
    <div class="wrap">main</div>
  </div>
  <div class="aside">aside</div>
</div>

<style>
.section {
  *zoom: 1;  /*兼容IE6/7*/
}

.section:after {  /*IE8不支持::*/
  content: '';
  display: block;
  clear: both;
}

.main {
  width: 100%;     /*step 3*/
}

.main .wrap {
  margin-left: 100px; /*step 5*/
  background: yellow; /*step 5*/
  min-height: 200px;  /*step 5*/
}

.aside {
  width: 100px;     /*step 1*/
  background: red;  /*step 1*/
}

.main, .aside {
  float: left;      /*step 2*/
}

.aside {
  margin-left: -100%;  /*step 4*/
}
</style>

https://codepen.io/jirengu/pen/mdrJxKo


前端剑指offer系列已更文章​mp.weixin.qq.com

关注公众号 【编程公子】,早7天获取文章更新,每日更新一篇,刷遍大厂题。下图是更新预告

831bf4a097207c5a438ec1bcca5ed684.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值