经典布局问题

开篇之前先了解一个问题:

浏览器在解析HTML结构的时候,是按标签顺序加载渲染的.也就是说,当块元素足够大,网速不好的时候,块是被一片一片加载出来.


图一

就上图的布局,掐指一算有4,5中方法:

absolute + margin 方式

HTML

<header id="hd">头部</header>
<div id="bd">
    <aside id="aside">侧边栏固定宽度</aside>
    <div id="main">主内容栏自适应宽度</div>
</div>
<footer id="ft">底部</footer>

CSS

#aside{
    position:absolute;
    top:0;
    left:0;
    width:200px;
}
#main{
    margin-left:210px;
}

我们使用了 absolute,即让 ‘#aside’ 脱离常规流,通过绝对定位到想要的位置,同时主内容栏自适应宽度.

同时,我们想让主内容优先显示,改变Aside和main顺序,让main先加载

HTML优化

<header id="hd">头部</header>
<div id="bd">
    <div id="main">主内容栏自适应宽度</div>
    <aside id="aside">侧边栏固定宽度</aside>
</div>
<footer id="ft">底部</footer>

我们不改变页面布局,调整HTML标签顺序,在通过css重排:

CSS优化

#aside{
    position:absolute;
    top:0;
    right:0;
    width:200px;
}
#main{
    margin-right:210px;
}

还是同样的结构,但是main主内容会被先加载.

问题

我们知道 absolute 是定位流,脱离正常排版,也就是说绝对定位元素不影响其上下文的排版方式 ,也就是说文本很多的时候,会溢出到父元素上classsic layout

有人说设置父元素 overflow:hidden 那么溢出部分将会被裁减,同样不符合布局意图,无法可破。所以在内容量不可控的场景,不推荐使用这种方式。

float + margin 方式

absolute + margin 方式一样,float + margin 方式一样是经典的利用来布局的方案,并且被更广泛使用。仍然以 图一 为例,来看代码:

HTML

<header id="hd">头部</header>
<div id="bd">
    <aside id="aside">侧边栏固定宽度</aside>
    <div id="main">主内容栏自适应宽度</div>
</div>
<footer id="ft">底部</footer>

CSS

#aside{
    float:left;
    width:200px;
}
#main{
    margin-left:210px;
}

同样也能实现图一效果,而且aside盒子随内容拉伸.

我们让主内容优先显示:

  <style>
    #aside {
      float: left;
      width: 200px;
      border: 1px solid red;
    }
    #main { 
      border:1px solid rebeccapurple;
      margin-left: 210px;
    }
  </style>
</head>

<body>
  <header id="hd">头部</header>
  <div id="bd">
    <div id="main">主内容栏</div>
    <div id="aside">侧边栏</div>

  </div>
  <footer id="ft">底部</footer>
</body>

结果并不是我们想要的结果,aside的float已经被用margin-left的main挤到了下一行,很遗憾的告诉你这种方式无法支持主内容优先显示,我们看下一种:

float + 负margin 方式

这就是经典的圣杯布局。

HTML当然是使用主内容优先显示的那种:

HTML

<header id="hd">头部</header>
<div id="bd">
    <div id="main">主内容栏自适应宽度</div>
    <aside id="aside">侧边栏固定宽度</aside>
</div>
<footer id="ft">底部</footer>

CSS

#bd{
    padding-left:210px;
}
#aside{
    float:left;
    position:relative;
    left:-210px;
    width:200px;
    margin-left:-100%;
}
#main{
    float:left;
    width:100%;
}

简单解释一下上面的CSS Code,首先我们是在做一个左侧固定宽度,右侧自适应宽度的布局。我们说过要让块级元素在同行显示的条件:改变显示方式,改变流方式,这里我们选择了使用 float来将 #main#aside 变成浮动流。

OK,这时我们具备 #main#aside 能在同行显示的前置条件。我们知道,浮动元素其宽度如果没有显式定义,则由其内容决定。正好,#aside 是定宽的,所以显示给它定义 width:200px,但此时 #main 该怎么办?不设置 width 不对,因为宽度将被内容左右,设置 width:100% 也不对,因为这样的话,就没有 #aside 的立足之地了,正确的应该是 width: calc(100% - 200px),不是么?可惜,这是新特性,只好作罢。

变通?是的,有的时候稍微换个思路,你会觉得豁然开朗。

#main 不是要自适应吗?那就给它个 100%,怎么做?我们在包含块 #bd 中就将 #aside的宽度刨除,宽度全部都给 #main。恩,我们只需要这样 #bd{padding-left:210px;}(10px仍然是用来做间隙的),这时 #main 就可以设置 width:100% 了,由于 #bd 设置了 padding,所以已在左边预留出了一块宽 210px 的区域。此时的问题在于如果将 #aside 挪到这个地方,你想对了,我们是在聊 负margin 布局,自然需要利用上。

#aside{margin-left:-100%;} 这样可以了吗?很明显,这样还不行,此时 #aside#main 的起始位置将会重合,因为 #asidemargin-left 计算值是相对包含块来计算的,而此时包含块的宽度等于 #main 的宽度。

如何让 #aside 再向左偏移 210px?显然 margin 是不行了,因为我们已经用掉它了。这时我们可以借助相对偏移。

向左偏移 210px 是件很简单的事:#aside{position:relative;left:-210px;}

圣杯布局最终总结:

  1.HTML排版都是自适应div在最前面,然后是固定宽度div。

  2.都设置float:left。

  3.如果div在左边,则该div设置margin-left:-100%。如果div在右边,则该div设置margin-right:负自身宽度

  4.在左边的div设置相对定位的left值,如果是一个div,则该值是padding-left的值,也就是该div宽度与间隙之和的负值。如果左边是多个div,那么当前div的left值就是它右边所有的div的宽度与间隙的和再加上自身的宽度与间隙的值的负值。

  5.在右边的div设置相对定位的right值,该值是自身的间隙的负值。如果右边是多个div,那么当前div的right值就是它左边所有的div的宽度与间隙的和再加上自身的间隙的值的负值。

  6.这些div的外层的大盒子设置padding值,这个值是左边或者右边div的宽度与间隙的和。例如左边一个固定宽度的div,宽度为50,间隙是15;然后右边两个固定宽度的div,宽度分别是80、100,间隙都是10.那么padding值就应该设置为padding:0 200px 0 65px;

  7.自适应div的宽度设置为100%,其它的都不用管。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值