flex布局-最后一个元素margin-right失效要怎么处理?

1、前言

     电商系统中,为了拉新、促活、复购等, 会推送一些优惠券给到用户, 其中针对新用户的新人券基本是每个电商平台都有的工具。

下面为某社区团购小程序针对新人的新人券模块(图片截取其小程序、若有问题请联系删除)。
初始化看到的样式: image.png 滑动到最右侧的样式: image.png
作为技术人员, 从结构上来猜测该模块的技术实现是:
-1张券&2张券&3张券的样式均不同;
-4张及以上的支持左右滑动、第一张&最后一张的边距要保留.
设想可能的UI如下简化版:
优惠券样式图.png
下面我们看看如何实现优惠券大于等于4张时的效果, 需要满足如下几个条件:

  1. 初始化时、左侧边距该保留;
  2. 滑动过程中、左侧边距不在、内容可直接顶到左边;
  3. 滑动到最后一张券、最右侧的边距该保留;

接下来我们看看该如何实现这个逻辑~.

2、Demo

2.1 父元素宽度固定

我们先看下如下代码运行效果图:

<view class="contanier">
  <view class="coupons">
    <view class="coupons-item">券item</view>
    <view class="coupons-item">券item</view>
    <view class="coupons-item">券item</view>
    <view class="coupons-item">券item</view>
  </view>
</view>

.coupons {
  width: 654rpx;
  border: 1rpx solid red;
  margin: 0 auto;
  padding-left: 30rpx;
  /* 不加这个你会发现: 加上了padding-left的值, width就变成不是654rpx了 */
  box-sizing: border-box;
  display: flex;
  flex-direction: row;
  align-items: center;
  overflow: auto
}
.coupons-item {
  width: 190rpx;
  height: 162rpx;
  color: #E50401;
  background: #fff;
  margin-right: 12rpx;
  /* 指定flex的收缩规则: 需要、不然会被收缩未真实展现item的width */
  flex-shrink: 0;
}
复制代码

我们可以发现: 该Demo满足了1&&2的条件:
image.png image.png

But条件3未满足: 滑动到最后一张券、最右侧的边距该保留~
思考: 该如何实现讷?
通过审查元素发现: 最后一个元素的margin-right是有渲染的、只是没有作用到该作用的地方,如下图:
image.png

网上有一种说法是说设置的宽度太短、导致对齐的时候没有按照正常方式对齐, 我们看下是什么意思~
简单来说就是外层设置个预期容器的宽度, 然后内层盒子的宽度为优惠券张数*190[单个item宽度] + 多个边距值 + padding预留的空间, 这样的话就刚好展示右侧边距.

.contanier {
  margin:  0 auto;
  width: 654rpx;
  overflow: auto;
}
.coupons {
  width: 856rpx;
  border: 1rpx solid red;
  margin: 0 auto;
  padding-left: 30rpx;
  /* 不加这个你会发现: 加上了padding-left的值, width就变成不是654rpx了 */
  box-sizing: border-box;
  display: flex;
  flex-direction: row;
  align-items: center;
  overflow: auto
}

.coupons-item {
  width: 190rpx;
  height: 162rpx;
  color: #E50401;
  background: #fff;
  margin-right: 12rpx;
  /* 指定flex的收缩规则: 需要、不然会被收缩未真实展现item的width */
  flex-shrink: 0;
}
复制代码

But该方法下: 在优惠券数量依赖接口返回时,该写法就非常不灵活、需要不断计算实际滑动盒子的width、不推荐。

2.2 max-content

flex容器外面套了一层view,给外面的view设置overflow:auto, 给flex容器设置 width:max-content.

.contanier {
  margin:  0 auto;
  margin-top: 100rpx;
  margin-bottom: 100rpx;
  overflow: auto;
}
.coupons {
  border: 1rpx solid red;
  padding-left: 30rpx;
  box-sizing: border-box;
  display: flex;
  flex-direction: row;
  align-items: center;
  overflow: auto;
  /* 关键~ */
  width: max-content;
}
复制代码

至此, 你就会发现最后一个元素的margin-right生效了: image.png
这里还有个小问题就是: 每个元素的margin-right:12rpx不适合用于最后一个元素、他应该跟第一个元素的padding-left:30rpx匹配, 故需要再加多如下css:

.coupons-item:last-child {
  margin-right: 30rpx;
}
复制代码

最终, 我们看下效果图是否满足开头的3个条件:

  1. 初始化时、左侧边距该保留;

image.png
2. 滑动过程中、左侧边距不在、内容可直接顶到左边;
image.png
3. 滑动到最后一张券、最右侧的边距该保留;
image.png

width: max-content能实现、但是不清楚啥意思、故特意去研究了下, 研究结果如下文~

2.3 css3新增width值简介

在css3中, 新增了几个属性值: max-content/min-content/fit-content等, 下面重点介绍max-content.

若容器有足够的宽度, 足够的空间, 此时所占据的宽度就是max-content所表示的尺寸。

大白话翻译: 采用内部元素宽度值较大的那个元素宽度作为最终容器的宽度~
啥东西, 每个字我都认识, 组装在一块就理解不了, 先看看下面的Demo吧

<view class="bg">未使用css3新属性:max-content</view>
<view class="bg bg2">使用css3新属性:max-content</view>

.bg {
  background: #E50401;
  margin-bottom: 10rpx;
}
.bg2 {
  width: max-content;
}
复制代码

你会发现view默认是占据父元素100%宽度的, 因为设置了max-content属性而变成了类似行内元素的属性表现.
image.png
这里就牵扯到css尺寸: 内在尺寸&外在尺寸
-内在尺寸: 是由元素包含的内容量来决定的;
-外在尺寸: 为元素设定的width/height, 是固定值。

// view这种块级元素、默认宽度为父元素的100%的宽、是外在尺寸
// 若需要根据元素的实际内容来设置尺寸, 这个就是内在尺寸.
复制代码

max-content代表的值会随着元素的实际内容的改变而变化.

3、最后

flex横向滚动布局中, 最后一个元素margin-right失效可试试用max-content的方式去实现。

猜你喜欢

转载自juejin.im/post/7042879113127804941