Beace Lee

Beace Blog

Written by Beace Lee who lives and works in China building useful things. You should follow him on Twitter

div始终位于底部的问题

January 16, 2017

背景

在阅读Flexbox Patterns文章时,发现曾经解决过如下问题。在此作为记录。

需求描述

对于常见的列表或者卡片布局时,宽度往往统一,高度参差不齐。如果想要实现风格一致的卡片或者列表,如下图所示,当描述文字高度不一致时,最底的价格始终保持在最下面,每两个对齐。

实现方式

DOM结构

对于手机端而言,没有太多的 浏览器兼容性问题。整个布局比较简单,DOM结构代码如下所示。

<div class="card-container">
        <div class="card card--flexdWidth">
            <div class="card__description">
                <div class="icon fa fa-flask card__descriptionIcon"></div>
                <div class="card_descriptionText">
                    Science potion Science potion Science potion
                </div>
            </div>
            <div class="card__price">Cost $5</div>
        </div>
        <div class="card card--flexdWidth">
            <div class="card__description">
                <div class="icon fa fa-flask card__descriptionIcon"></div>
                <div class="card_descriptionText">Science potion</div>
            </div>
            <div class="card__price">Cost $5</div>
        </div>*4
    </div>

这里,我添加了许多5个结构相同的card组件,唯一有点区别的是第一个card组件的文字内容稍微多些。为了测试我的最终效果。

STYLE

大体的样式比较简单

  • 最外层盒子display属性为flex,并且flex-wrapwrap允许换行,宽度为100%
  • 每一个card组件宽度为50%,基数时盒子右边添加一个边框,这时会将第二个card挤下去,因此为改盒子添加了box-sizing:border-box属性。
  • 其中每一个card内部,display也为flexflex-direction为垂直方向。
* {
        margin: 0;
        padding: 0
    }
    html,
    body {
        width: 100%
    }
    .card-container {
        display: flex;
        width: 100%;
        flex-wrap: wrap;
    }
    .card {
        display: flex;
        flex-direction:  column;
        overflow: hidden;
        border-bottom: 1px solid #cad0d2;
        box-sizing: border-box;
    }
    .card:nth-child(odd) {
        border-right: 1px solid #cad0d2;
    }
    .card__description {
        display: flex;
        flex-direction: column;
        align-items: center;
        padding: 15px 0;
        font-size: 2em;
        margin-bottom: 10px;
    }
    .card_descriptionText {
        color: #57727c;
        font-size: 1em;
        text-align: center;
        max-width: calc(100% - 30px);
    }
    .card__price {
        text-align: center;
        color: #57727c;
        font-size: 1em;
        font-weight: 700;
        padding: 5px 15px;
    }
    .card--flexdWidth {
        width: 50%;
    }

到这里,样子大概是这样。

这时候就可以发现问题出现了,当描述内容的字相差不太多时,还可以看到展现方式比较一致,当字数相差许多,盒子被不断撑开时,价格的位置就显得不太一致。

解决思路

可以想到,flex布局中,控制子元素属性——align-self,如果flex布局中方向为垂直,则其根据父元素自动计算垂直有关属性;同样,如果为水平,根据父元素计算水平有关属性。flex中,有如下常用属性。

属性 解释
center 垂直/水平居中
flex-start 始终在flex的开始
flex-end 始终在flex盒子的底部

了解到这里,可以通过设置每一个card的中的布局跟最外层card-container一致,如下。

.card {
    display: flex;
    flex-direction: row; //由垂直改为水平
    flex-wrap: wrap; //flex 元素 被打断到多个行中
    justify-content: center; //内容水平居中
    overflow: hidden;
    border-bottom: 1px solid #cad0d2;
    box-sizing: border-box; //忽略border
}
.card__price {
   align-self: flex-end; //一直保持在flex box的底部
}

总结

需要注意的是,其父元素的flex属性必须为row,且flex-wrap属性必须为wrap,这样card组件中的价格才能保持在flex盒子中的底部位置。