css虽简单,但细节多,技巧性高,易学难精。
如何实现左右固定300px , 中间宽度自适应?
有如下结构
<div class="wrapper">
<div class="item left">左</div>
<div class="item right">右</div>
<div class="item center">中</div>
</div>
公有样式, 设置高,设置左右宽度固定300px,左右为红色,中间为黄色。
.item {
height: 400px;
}
.left,
.right {
width: 300px;
background: #f00;
}
.center {
background: yellow;
}
一. 双浮动法
.left {
float: left;
}
.right {
float: right;
}
原理: float不会完全脱离文档流,会占用原空间
MDN官方解释:该元素从网页的正常流动(文档流)中移除,尽管仍然保持部分的流动性(与绝对定位相反)。
问: 为什么 center 要放在leftr和right之后?
答:
浏览器加载页面顺序是从上到下,
left已经左浮动,right右浮动。渲染center时,浏览器忽略掉已经脱离文档流的left和right ,center元素会从头占满整行,但发现left还占用着300px ,右边right又占用了300px,所以center的宽度在left和right之间,达到宽度自适应
二. 绝对定位法
<style>
.left {
position: absolute;
top: 0;
left: 0;
}
.right {
position: absolute;
top: 0;
right: 0;
}
.center {
margin: 0 300px;
}
</style>
<div class="wrapper">
<div class="item left">左</div>
<div class="item center">中</div>
<div class="item right">右</div>
</div>
原理: 左右绝对定位,脱离文档流 。 中间不设置宽度,只设置左右边距,自动撑满块级元素一行的剩余空间
三. 弹性盒子
.wrapper {
display: flex;
}
.center {
flex: 1;
}
父容器设置 display: flex,左右设置300px, center把flex设置为1 ,效果是否实现了呢?
浏览器运行,看上去是对的 ,但实际上屏幕缩小后左右不是固定的300px,宽度会被压缩。
还需要再添加如下样式:
.left,.right {
flex-shrink: 0; /*等同flex:0 0 auto */
}
原理:flex:1 实际上是三个属性的简写 , flex:1;
等同于 flex:1 1 auto;
。
简单的说,分别代表:剩余空间 容器缩小时压缩比例 最小宽度。具体细节参考:MDN -- 弹性盒子
由此得知,center设置flex:1;
,即为flex:1 1 auto;
(自动占满容器剩余宽度 默认压缩比例 默认最小宽度)
left和right设置 flex-shrink: 0;
,flex-shrink就是flex简写中的第二个属性, 等同 flex:0 0 auto;
(没有设置自动占满容器剩余宽度 0不压缩 最小宽度默认auto)
问: 为什么left和right设置flex-shrink: 0;
等同flex:0 0 auto
,其中最小宽度为auto,但是宽度依旧固定为300px?
答: 最小宽度为auto是默认值 , 优先级小于具体元素设置的width。如果设置flex:0 0 400px
,那么左右最小宽度为400px,优先级高于元素设置的width
四. 网格布局 grid
最简单的网格布局
.wrapper {
display: grid;
grid-template-columns: 300px 1fr 300px;
}
快速理解: grid-template-columns为父容器属性,并非表示上右下左,而是表示三个子元素的宽度为 (300px 自动占满1份剩余空间 300px),如果写 grid-template-columns: 300px 1fr 2fr 100px;
即表示四个子元素宽度分别为300px 1/3剩余空间 2/3剩余空间 100px
五. 表格布局
.wrapper {
width: 100%;
display: table;
}
.wrapper>.item:not(.center) {
display: table-cell;
}
把左右元素设置为单元格即可,不过该方法在屏幕缩小时,左右固定300px会被压缩
问: 为什么要设置width为100%?
答: display:table 与table元素类似 ,实际上是行内块级元素, 而不是块级元素。
表格不能自动响应: 当你使用正确的布局容器 (比如<header>
,<section>
,<article>
, 或是<div>
是一个通用型的流内容容器,在不使用CSS的情况下,其对内容或布局没有任何影响。")), 它们的默认宽度是父元素的 100%. 而表格的的默认大小是根据其内容而定的。因此,需要采取额外的措施来获取表格布局样式,以便有效地在各种设备上工作。
六. css计算 、 JS计算
① calc计算
.wrapper {
white-space: nowrap;
font-size: 0;
-webkit-text-size-adjust: none;
}
.item {
display: inline-block;
}
.center {
width: calc(100vw - 300px * 2);
}
原理:只要把div放在同一行,使用calc计算宽度即可 , font-size: 0;-webkit-text-size-adjust: none;
是为了消除inline-block的间隙,其他方法亦可
② js计算
.wrapper {
white-space: nowrap;
font-size: 0;
-webkit-text-size-adjust: none;
}
.item {
display: inline-block;
transition: 0.4s;
}
<script>
window.onload = function() {
function computed() {
const oCenter = document.querySelector(".wrapper .center")
oCenter.style.width =
innerWidth - 300 * 2 < 0 ? 0 + "px" : innerWidth - 300 * 2 + "px"
}
computed()
var timer = null
window.addEventListener("resize", () => {
clearTimeout(timer)
timer = setTimeout(computed, 300)
})
}
</script>
与calc一致,计算出相对宽度即可
总结:
绝对定位法脱离文档流,易带来布局问题。
grid布局简单强大,移动端兼容性好,
js方法万能,但不易维护
推荐使用flex 、grid。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。