supce's blog

CSS学习笔记之两列页面布局(二)

上一篇学习了两列定宽和两列自适应结构并且遗留了一个两列不等高的问题,今天就把两者结合一下试试,并且学习一些解决两列不等高问题的方法

一、单列定宽单列自适应结构


上一次学习到如果两列的盒模型宽度总和超过父元素的宽度,或者大于100%,就会发生错位的现象。但是,如果让一列的宽度采用百分比或者auto,一列的宽度采用像素,怎么才能让这两个宽度单位不同的盒子组合在一起,完美实现单列定宽单列自适应结构。
下面我们就来学习一个,提高一下自己的滋似水平!▇-▇ ,将上节的代码稍微修改一下,把mainBox的宽度设置为70%,sideBox的宽度设置为200px。

<style type="text/css">
    ……
    .mainBox{
        float: left;
        width: 70%;
        color: #FF0000;
        background-color: #333333;
    }
    .sideBox{
        float: right;
        width: 200px;
        color: #FFFFFF;
        background-color: #999999;
    }
    ……
</style>

如果将页面缩小,就会发生错位现象:

为了解决这个问题,先尝试给sideBox增加一个负的外边距试试 marigin-left: -200px 这时候再将浏览器窗口缩小效果如下:

虽然不像上次发生错位,但是却发生了重叠,这并不是我想要的结果。于是,再尝试将mainBox的width设置为auto。

<style type="text/css">
    ……
    .mainBox{
        float: left;
        width: auto;
        color: #FF0000;
        background-color: #333333;
    }
    .sideBox{
        float: right;
        width: 200px;
        margin-left: -200px;
        color: #FFFFFF;
        background-color: #999999;
    }
    ……
</style>

刷新页面,好像问题是解决了。

但是我们将mainBox中的增加内容,会发现又发生了覆盖,看来这个思路是不行了。

换个思路。float看来已经不行了,那可以尝试一下定位的方式。先设置父元素container相对定位,使其子元素在定位的时候有参照物。然后设置mainBox的右外边距为200px,给sideBox腾出空白的空间,防止覆盖。

<style type="text/css">
        *{
            padding: 0;
            margin: 0;
        }
        #header,#footer{
            width: 100%
            height: 30px;
            background: #E8E8E8;
        }
        #container{
            position: relative;
            margin: 10px 0;
        }
        .mainBox{
            width: auto;
            margin-right: 200px;
            color: #FFFFFF;
            background-color: #333333;
        }
        .sideBox{
            position: absolute;
            top: 0;
            right: 0;
            margin-left: -200px; /*使用负边距使sideBox向左浮动缩进*/
            width: 200px;
            color: #FFFFFF;
            background-color: #999999;
        }
        /*#container:after{
            display: block;
            visibility: hidden;
            font-size: 0;
            line-height: 0;
            clear:both;
            content: "";
        }
        #footer {
            clear:both;
        } */
    </style>

效果如下图:

这样就得到了我们想要的结果,但是这种方法是不得已而为之的。使用绝对定位后,浮动与清除浮动都会无效,而且会导致一个严重的问题————使用绝对定位的元素无法撑开父元素的高度,而且会覆盖其他元素的内容。比如下图:

在文档流的文章中会详细介绍定位等相关内容,上面两种方法都没有完全达到所需要的效果。在下一篇有关三列布局的文章探讨了一种更好的方法

二、两列等高


上一节中带来了一些高度问题,我们可以用下面四种方法来解决。每种方法都有自己的优点和缺点,可以根据自己的具体使用环境来选择。

1、背景模拟

最简单和最直接的办法是背景模拟。背景模拟就是利用背景图片的平铺,在视觉上产生等高的感觉。背景图片必须是一张可以Y轴重复的图片。即background-repeat: repeat-y;
为了实现两列等高,背景图片也必须是两列的存在形式,如下图:

在开始实验之前,先将实验要用的骨架搭建好

<div id="header">头部信息</div>
<div id="container">
    <div class="mainBox">
        <p>主要内容区域</p>
        <p>多添加几行文字试试效果</p>
        <p>多添加几行文字试试效果</p>
        <p>多添加几行文字试试效果</p>
        <p>多添加几行文字试试效果</p>
    </div>
    <div class="sideBox">这是侧边栏</div>
</div>
<div id="footer">底部信息</div>

骨架已经搭好,利用上面的背景图开始等两列高实验

<style type="text/css">
    *{
        padding: 0;
        margin: 0;
    }
    #header, #footer{
        width: 960px;
        height: 30px;
        background-color: #E8E8E8;
    }
    #container{
        width: 960px;
        background: url(images/bg.png) repeat-y 0 0;
    }
    .mainBox{
        float: left;
        width: 650px;
    }
    .sideBox{
        float: right;
        width: 280px;
    }
    .mainBox,.sideBox{
        padding: 0 5px;
        color: #FF0000;
    }
    #container:after{
        display: block;
        visibility: hidden;
        line-height: 0;
        font-size: 0;
        clear: both;
        content: ""
    }
</style>

刷新一下页面,看下效果:

利用背景图片实现两列“等高”只是在mainBox和sideBox两个元素的父元素中添加了背景图片,并纵向重复,无论mainBox比sideBox高,还是sideBox比mainBox高,在视觉上实现了等高,其实是较高的子元素将父元素撑高了而已。
这种方法有着其自己的优点:

  • 实现方法简单,只需要一张能够纵向重复的图片
  • 保持简洁的HTML代码结构和简单的CSS样式代码

缺点:

  • 宽度必须固定,无论修改页面中mainBox还是sideBox的宽度,都需要修改图片,影响了效率和页面的重构
  • 左右两列互换或者页面结构变化,也必须修改图片
    所以,在页面结构基本不变动的情况下,可以使用这种方法来产生视觉上的等高。

2、负边距实现

使用负边距实现等高,主要是给mainBox和sideBox这两个容器添加margin-bottompadding-bottom两个属性,同时给父容器container添加了overflow属性。
在保持HTML结构不变的同时,试着修改为如下CSS代码:

<style type="text/css">
        *{
            padding: 0;
            margin: 0;
        }
        #header, #footer{
            width: 960px;
            height: 30px;
            background-color: #E8E8E8;
        }
        #container{
            width: 960px;
            /*background: url(images/bg.png) repeat-y 0 0;*/
            overflow: hidden;
        }
        .mainBox{
            float: left;
            width: 650px;
            background-color: #333333;
        }
        .sideBox{
            float: right;
            width: 280px;
            background-color: #999999;
        }
        .mainBox,.sideBox{
            padding: 0 5px;
            color: #FF0000;
            margin-bottom: -9999px;
            padding-bottom: 9999px;
        }
        #container:after{
            display: block;
            visibility: hidden;
            line-height: 0;
            font-size: 0;
            clear: both;
            content: ""
        }
    </style>

效果如下图所示:

padding可以显示容器的背景色,而设置margin为负值可以将其他容器吸到自己的身边。上面的例子中将padding设置为9999px,虽然拉高了容器的高度,但是能够使背景在很大的范围内显示,将margin设置为-9999px,能够将footer吸到自己的身边。然后将父容器container的overflow设置为hidden,就可以将不需要的部分隐藏,这样就实现了视觉效果上的等高。

该方法并不建议使用,在这里折腾下主要就是拓宽一下自己的CSS思路

当然,这种方式还可以结合背景模拟来使用,将mainBox和sideBox两个容器的背景色去除,同时给container容器添加背景图。

<style type="text/css">
    *{
        padding: 0;
        margin: 0;
    }
    #header, #footer{
        width: 960px;
        height: 30px;
        background-color: #E8E8E8;
    }
    #container{
        width: 960px;
        background: url(images/bg.png) repeat-y 0 0;
        overflow: hidden;
    }
    .mainBox{
        float: left;
        width: 650px;
    }
    .sideBox{
        float: right;
        width: 280px;
    }
    .mainBox,.sideBox{
        padding: 0 5px;
        color: #FF0000;
        margin-bottom: -9999px;
        padding-bottom: 9999px;
    }
    #container:after{
        display: block;
        visibility: hidden;
        line-height: 0;
        font-size: 0;
        clear: both;
        content: ""
    }
</style>

效果如下:

3、边框模拟

边框模拟其实就是利用边框的颜色来代替另一列的背景色。下面,试试将mainBox的边框颜色来代替sideBox的背景色。

<style type="text/css">
    *{
        padding: 0;
        margin: 0;
    }
    #header, #footer{
        width: 960px;
        height: 30px;
        background-color: #E8E8E8;
    }
    #container{
        position: relative;
        width: 960px;
        overflow: hidden;
    }
    .mainBox{
        float: left;
        width: 680px;
        border-right:280px solid #AAAAAA;
        color: #FFFFFF;
        background-color: #333333;
    }
    .sideBox{
        position: absolute;
        top: 0;
        right: 0;
        width: 280px;
        color: #FFFFFF;
    }
    .mainBox,.sideBox{
        color: #FF0000;
        margin-bottom: -9999px;
        padding-bottom: 9999px;
    }
    #container:after{
        display: block;
        visibility: hidden;
        line-height: 0;
        font-size: 0;
        clear: both;
        content: ""
    }
</style>

效果如下图所示:

由于使用了绝对定位,所以带来了一个致命的缺点,就是定位的容器高度如果超过非定位容器的高度,此时并不能撑开父容器的高度,所以在效果上就不是等高的了。

4、其他方式

两列等高使用CSS的代码来实现主要还是利用了CSS样式能够在页面中进行多样的表现,最终只是给用户在视觉上的高度是相等的。而真正意义上的等高应该是两列的高度在任何时候都是相同的。
但是如果给两列都固定了相等的高度值就无法实现高度的自适应。因此,我们可以利用JavaScript来实现两列等高,如果高度值不同,可以将高度进行重新定义。
我们设置如下HTML代码:

<div id="header">头部信息</div>
<div id="container">
    <div class="mainBox" id="mainBox">
        <p>主要内容区域</p>
        <p>多添加几行文字试试效果</p>
        <p>多添加几行文字试试效果</p>
        <p>多添加几行文字试试效果</p>
        <p>多添加几行文字试试效果</p>
    </div>
    <div class="sideBox" id="sideBox">这是侧边栏</div>
</div>
<div id="footer">底部信息</div>

试着将CSS样式修改为最基础的样式:

<style type="text/css">
    *{
        padding: 0;
        margin: 0;
    }
    #header, #footer{
        width: 960px;
        height: 30px;
        background-color: #E8E8E8;
    }
    #container{
        width: 960px;
    }
    .mainBox{
        float: left;
        width: 650px;
        background-color: #333333;
    }
    .sideBox{
        float: right;
        width: 280px;
        background-color: #999999;

    }
    .mainBox,.sideBox{
        color: #FFFFFF;
    }
    #container:after{
        display: block;
        visibility: hidden;
        line-height: 0;
        font-size: 0;
        clear: both;
        content: ""
    }
</style>

添加JavaScript代码:

<script type="text/javascript">
    mh = document.getElementById('mainBox');
    sh = document.getElementById('sideBox');
    mh.clientHeight < sh.clientHeight ? 
    mh.style.height = sh.clientHeight + "px":sh.style.height = mh.clientHeight + "px";
</script>

效果如下:

使用JavaScript脚本的方式相对来说是比较合理和实际的做法。CSS样式主要作用是修饰页面,主要为表现层。而判断是否等高这种行为层的事情还是用JavaScript来实现比较好。这样能够避免好多意想不到的问题。

15号要做汇报,时间又不够用了,更新要推迟了 (╯‵□′)╯︵┻━┻