本文为做者行舟客投稿,原文地址:css
https://yunxiaomeng.blog.csdn.net/article/details/108821829html
欢迎点赞!前端
最近为我开源的小项目:微信小程序扩展自定义组件库(点击去GitHub) 增长了一个新组件 —— 日历组件。css3
在编写过程当中,由于你们都知道,日历组件是有固定行数和每一行的固定列数的(即便当前方块内没有值),因此结合小程序“数据优先”的特色,最合适的布局方式必定是flex了!小程序
说一下大体思路(布局上),笔者将整个组件分为两部分:分别是微信小程序
头部的布局自很少说:一个 display:flex;
加上 align-items:center;
居中简直完美。底部的日期显示我是采用的“将总体分为六行,每一行七列”的布局方式 —— 由于一个月最多31天,每一周最多7天,6X7=42,行数六行足够使用。(并且如今基本上日历都是6行7列的)微信
这样的话我就给每一行设置相同的class,让其再用flex规范子元素(子组件):ide
<view class="calendar_panel calendar_panel_two">
<view class="calendar_box">
<view class="weekday_label">日</view>
<view class="weekday_label">一</view>
<view class="weekday_label">二</view>
<view class="weekday_label">三</view>
<view class="weekday_label">四</view>
<view class="weekday_label">五</view>
<view class="weekday_label">六</view>
</view>
<view class="calendar_box" wx:for="{{dateList}}" wx:for-item="week" style="{{index==0?'justify-content:flex-end':''}}">
<view class="weekday_label {{(item.value==selectedDate)?'active_date':''}} {{(item.value==now_selectedDate)?'active_dates':''}}" wx:for="{{week}}">
<view class="" bindtap="selectDate" data-date="{{item}}">
{{item.date}}
</view>
</view>
</view>
</view>
(代码中倒数第7、八行的判断是检验是不是当前日期(now_selectedDate)或选中日期(selectedDate),为其加特殊效果,对布局不形成影响)函数
.calendar_panel{
width: 100%;
height: calc(100% - 56rpx);
}
.calendar_panel_two{
display: flex;
flex-direction: column;
justify-content: space-around;
}
.calendar_box{
width: 100%;
background: #fff;
overflow: hidden;
display: flex;
justify-content: space-around;
height: calc(100% / 6);
align-items: center;
}
.weekday_label{
font-size: 27rpx;
padding: 12rpx 0;
display: flex;
align-items: center;
overflow: hidden;
}
.weekday_label>view{
box-sizing: border-box;
padding: 20%;
}
.select_icon{
width: 30rpx;
height: 30rpx;
}
.active_date{
background: rgba(0,0,0,.12);
color: rgba(0,0,0,.6);
overflow: hidden;
position: relative;
}
.active_dates{
background: rgba(0,0,0,.1);
color: rgba(0,0,0,.5);
position: relative;
}
.active_dates::before{
content: "今天";
position: absolute;
top: 0;
left: 50%;
transform: translateX(-50%);
color: blue;
font-size: 20rpx;
}
布局方完成,我满心欢喜的按下ctrl+s,发现:布局
能够看到:控制每一行的类是 “calendar_box”,那么毫无疑问,致使出现如图缘由确定是此类中有这样一行代码:
justify-content: space-around;
果不其然!
在本项目中,个人解决方法很简单:将这一行代码去掉,那么由此致使的宽高问题怎么解决?这个问题,css给出了解决方案—— calc()
!我将“每一行”的高度设为外部view的1/6:height:calc(100% / 6)
,每一行中列的宽度设为整行宽度的1/7:width:calc(100% / 7)
根据CSS文档流的特色,这些元素就会一个接一个的排列,贼好看的那种~(去这里)
★有了calc等css3函数的“加盟”,能够预见这种纯‘原生’的解决方式将会愈来愈多的被使用到各类场景。
”
sucess
刚才说了,这个案例中的行列数是固定的 —— 这并很多见!那么,除了本文提出的解决方法,还能怎么作?
动态改变最后一个元素的宽度
咱们都知道,flex布局中还有一个比较著名的概念就是 flex: 1;
(flex: auto;
)了,他能动态“填满”剩余空间,那么咱们再子元素同级位置再加一个元素,对他设置最小宽度为子元素相同宽度,而且margin和子元素一致:
<div class="container">
<div class="list"></div>
<div class="list"></div>
<div class="list"></div>
<div class="list"></div>
<div class="list"></div>
<div class="list"></div>
<div class="list"></div>
<div class="list"></div>
<i class="lists"></i>
</div>
.container {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
.list {
width:100px;
height:100px;
background-color: skyblue;
margin: 10px;
}
i.lists{
min-width:100px;
margin: 10px;
}
这个方法和下一个问题的第一种方法相似,但要简单不少!
根据个数最后一个元素动态margin
简单来讲就是:单独设置最后一行的最后一个元素,控制其margin-right 因为每一列的数目都是固定的,所以,咱们能够计算出不一样个数列表应当多大的margin值才能保证彻底左对齐。例如,假设每行4个元素,结果最后一行只有3个元素,则最后一个元素的margin-right大小是“列表宽度+间隙大小”的话,那最后3个元素也是能够完美左对齐的。而后,借助树结构伪类数量匹配技术,咱们能够知道最后一行有几个元素。例如:
.container {
display: flex;
/* 两端对齐 */
justify-content: space-between;
flex-wrap: wrap;
}
.list {
width: 24%; height: 100px;
background-color: skyblue;
margin-top: 15px;
}
/* 若是最后一行是3个元素 */
.list:last-child:nth-child(4n - 1) {
margin-right: calc(24% + 4% / 3);
}
/* 若是最后一行是2个元素 */
.list:last-child:nth-child(4n - 2) {
margin-right: calc(48% + 8% / 3);
}
那么,若是每一行的列数是不固定的呢?
这个问题的解法有不少种,其中笔者最“推崇”的是——用空白元素占位!使用足够的空白标签进行填充占位:具体的占位数量是由最多列数的个数决定的,例如这个布局最多7列,那咱们可使用7个空白标签进行填充占位,最多10列,那咱们须要使用10个空白标签。
<div class="container">
<div class="list"></div>
<div class="list"></div>
<div class="list"></div>
<div class="list"></div>
<div class="list"></div>
<div class="list"></div>
<div class="list"></div>
<i></i><i></i><i></i><i></i><i></i>
</div>
这种方法的缺点(同时也是优势)就是:占位的 <i>
元素宽度和margin设置必须和列表父元素同样便可!
.container {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
margin-right: -10px;
}
.container .list {
width: 100px;
height:100px;
background-color: skyblue;
margin: 15px 10px 0 0;
}
/* 和列表同样的宽度和margin值 */
.container > i {
width: 100px;
margin-right: 10px;
}
这里要左对齐,则设置i的margin-right;一样的若是右对齐,则需设置margin-left。
还有一种目前被不少人接受的方法就是曾经风靡的grid布局—— 它有自然的单侧对其和方块间隙,对熟悉grid的人来讲,本文这个问题几乎不会出现:
/** html代码 */
<div class="container">
<div class="list"></div>
<div class="list"></div>
<div class="list"></div>
<div class="list"></div>
<div class="list"></div>
<div class="list"></div>
<div class="list"></div>
</div>
/** CSS代码 */
.container {
display: grid;
justify-content: space-between;
grid-template-columns: repeat(auto-fill, 100px);
grid-gap: 10px;
}
.list {
width: 100px;
height:100px;
background-color: skyblue;
margin-top: 5px;
}
最后再介绍一下这个组件:它在调用时接收两个参数——他们是两个event函数,你须要监听他们,你能够获得:刚显示组件时的当前日期/星期几和你点击选中日期时选中的年月日和星期几
之后可能为组件增长什么功能就把布局方式更新了,到时候再回来补。
临近国庆学校没啥课,电脑放工做室没带回,室友电脑有点不会用,就到这吧。祝各位中秋&国庆快乐,嘿嘿!
最后
欢迎加我微信(winty230),拉你进技术群,长期交流学习...
欢迎关注「前端Q」,认真学前端,作个专业的技术人...