CSS Flex column排列时的容器宽度问题

来源:互联网 发布:特朗普 知乎 编辑:程序博客网 时间:2024/06/06 08:29

最近在学习Flex布局,想模仿小米首页的商品Tab页效果:

小米官网Tab页效果

仔细推敲可以发现,图中商品的陈列方式并不是一行一行的,而是一列一列的。当第一列排满后,剩下的一项“彩虹7号电池”会被排到第二列。

DOM的文档流通常是从左到右、自上而下横向排列元素的。像这种列式排列的,可以用JavaScript实现。但如果想用纯CSS实现,就会有些难度。

你可能首先会想到使用Flex布局,把主轴方向设置为垂直方向。虽然这样商品竖着排列了,但是你会发现,随着商品列数的增加,外层的容器并不会自动变宽

Flex外层容器不会自动变宽

这是Flex布局设计上的一个问题,可以参考这个StackOverflow提问。这里还有个DEMO更直观地阐述了这个问题:jsFiddle链接。

解决这个问题的办法有不少,对比下来最巧妙的办法就是:完全不考虑用Flex布局,利用writing-mode属性就能搞定。writing-mode是个平时用得很少的属性,原本是用来方排版竖向的文字,如中国古诗词。对writing-mode的历史感兴趣的话可以阅读 张鑫旭大神的文章。

writing-mode既然能让文字竖着排,也就能让容器内的元素竖着排。给商品列表的外层容器加上writing-mode属性,就能解决容器宽度的问题:

.tab-pane {    // lr可理解为left to right,即垂直方向上从左到右    writing-mode: vertical-lr; }

image.png

似乎不太对,容器内的所有元素都继承了竖向排版,没关系,把容器内的元素writing-mode重置成通常文档流的方向:

.tab-pane-items {    // tb可理解为top to bottom,即水平方向自上而下    writing-mode: horizontal-tb;}

最终效果图

这样就完美了。:-)

附完整例子代码:

<!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <meta name="viewport" content="width=device-width, initial-scale=1.0">  <meta http-equiv="X-UA-Compatible" content="ie=edge">  <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css">  <script src="https://cdn.bootcss.com/vue/2.4.4/vue.min.js"></script>  <style>  .list-group-item {    cursor: pointer;    border-radius: 0;    border: none;    background: rgba(0,0,0,.8);    color: white;    margin: 0;    position: static;  }  .tabs {    position: relative;    background: #eee;  }  .tabs .list-group {    width: 20rem;    margin-bottom: 0;  }  .tab-pane {    box-shadow: 0 5px 20px gray;    background: white;    padding: 2rem;    position: absolute;    left: 20rem;    height: 100%;    top: 0;    writing-mode: vertical-lr;  }  .tab-pane-items {    display: inline-block;    margin: 1rem 3rem 1rem 1rem;    color: black;    writing-mode: horizontal-tb;  }  span.image {    padding: 10px 20px;    margin-right: 1rem;    background: #ccccff;  }  </style>  <title>Document</title></head><body style="padding-top: 2rem;">  <div class="container" id="app">    <div class="tabs">      <ul class="list-group">        <li :class="['list-group-item', index==menu.active?'active':'']"           v-for="(item,index) in menu.items" @mouseover="menu.active=index"           @mouseleave="menu.active=-1" :key="index">{{item}}          <div v-show="menu.active==index" class="tab-pane">            <div v-for="n in (((index+1)*31)%19)" class="tab-pane-items">              <span class="image"></span>              <a href="#">iPhone手机</a>            </div>          </div>        </li>      </ul>    </div>  </div>  <script>  new Vue({    el: '#app',    data: {      menu: {        active: 1,        items: [          '手机 电话卡',          '笔记本',          '电视 盒子',          '路由器 智能硬件',          '移动电源 电池 插线板',          '耳机 音箱',          '保护套 贴膜',          '线材 支架 储存卡',          '箱包 服饰 鞋 眼镜',          '生活周边'        ]      }    }  });  </script></body></html>
原创粉丝点击