如何让商品标题类文本根据内容长度垂直居中

1. 前言

2. 使用 vertical-align 样式实现指定行数的垂直居中布局

3. 使用js计算文本所占总宽度,与文本盒子宽度比较追加不同类样式进行调整

4. vertical-align:middle的使用扩展——不限行数全展示垂直居中

5. 最好的方法:使用弹性盒子

前言:

如下图,商品标题内容字数不限,最多显示两行,多余省略。

展示上,标题显示一行和两行,图片右侧的文本部分的总高度是不一样的,而且在整个父层盒子中垂直居中(注:不是text-align:center,那是水平居中)。

解决方案:

1.使用 vertical-align 样式实现:

这种方法就比较简单了,不过需要注意的是这个属性只对行内样式有效,请先看该样式的说明:

vertical-align 属性设置元素的垂直对齐方式。
该属性定义行内元素的基线相对于该元素所在行的基线的垂直对齐。
允许指定负长度值和百分比值。这会使元素降低而不是升高。
在表单元格中,这个属性会设置单元格框中的单元格内容的对齐方式。

如上所述,如果你使用的是 float 进行的布局,那么这个样式可能会无效,所以先要保证左边图片和右边文本盒子都要是行内样式(可以使用display:inline-block)。

还有一点需要注意的是,弹性盒子貌似不支持这个样式,行内元素在弹性盒子中,该样式无效。

示例代码如下:

<!--wxml-->
  <view class='order' wx:for="{{orderList}}" wx:key="order_id">
    <image class='good_img' src='{{item.goods_small_img_url}}'></image>
    <view class='good_info'>
      <view class='good_name ellipsis_mul'>{{item.goods_name}}</view>
      <text class='expire_time'>{{item.expire_time}}</text>
    </view>    
  </view>

其中,elipsis_mul为app.wxss公共样式文件中定义的显示两行省略文本的公共类样式。

/*----公共样式----*/
/*文本省略--2行*/
.ellipsis_mul {
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-height: 1.5;
}

/*----页面样式----*/
.good_img {
  width: 204rpx;
  height: 204rpx;
  margin: 8rpx 20rpx;
  vertical-align: middle;
}

.good_info {
  width: 430rpx;
  overflow: hidden;
  padding-right: 16rpx;
  vertical-align: middle;
  display: inline-block;
}

.good_name {
  font-size: 32rpx;
  line-height: 42rpx;
  margin-bottom: 12rpx;
  word-break: break-all; /*数字字母换行*/
}

注:文本如果需要换行,需要加下  word-break: break-all; 不然,会出现的情况就是汉字是可以正常换行,但是数字和字母并没有换行。

2.使用js计算文本所占总宽度,与文本盒子宽度比较追加不同类样式进行调整:

结合js计算商品标题所占的总宽度,如果文本总宽度大于文本盒子宽度,那么就显示两行,否则显示一行。

1) 给文本盒子动态添加类样式以调整垂直位置:

<view class='order' wx:for="{{orderList}}" wx:key="order_id">
    <image class='good_img' src='{{item.goods_small_img_url}}'></image>
    <view class='good_info'>
      <view class='good_name {{item.titleStyle}}'>{{item.goods_name}}</view>
      <text class='expire_time'>{{item.expire_time}}</text>
    </view>    
  </view>

其中 item.titleStyle 为根据文本内容添加的不同类样式。

2)确定汉字、字母、数字及符号所占的宽度:

js 部分,需要先获取单个汉字、字母和数字所占的宽度,这个宽度跟文本所设置的字体大小有关,汉字的宽度等于字体大小,字母和数字及符号的宽度约大于半个字体宽度。

经验证,字母和符号所占的宽度差不多,所以统一取字母的宽度,这样就剩下字母和数字两种字符的宽度需要确定了。

先写一个用来计算的文本标签:

<view style='font-size:32rpx;'>
  <text class="computed"></text>
  <text class="computed">1</text>
  <text class="computed">a</text>
</view>

页面onload生命周期中,编写下面代码获取单个字符的宽度:

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function(options) {
    this.getWrodWidth(".computed")
  },
  getWrodWidth:function(selecter){
    var query = wx.createSelectorQuery().in(this)
    query.selectAll(selecter).boundingClientRect(function (res) {
      res.forEach(item=>{
        console.log(item.width)
      })
    }).exec()
  },

控制台输出结果如下:

根据上边得出的字符宽度封装函数计算商品标题的总宽度:

  /**
   * 获取文本总宽度的方法
   */
  getTextWidth: function(val) {
    var width = 0,
      wChinese = 16,
      wNnum = 9.375,
      wLetter = 8.84375;
    for (var i = 0; i < val.widthgth; i++) {
      var a = val.charAt(i);
      if (a.match(/[^x00-xff]/ig) != null) {
        //中文
        width += wChinese;
      } else if (a.match(/d/) != null){
        //数字
        width += wNnum;
      } else {  
        //字母和符号
        width += wLetter;
      }
    }
    return width;
  }

数据列表中进行如下处理:

  /**
   * 获取卡券列表
   */
  getCouponList: function() {
    var self = this;
    http.orderList().then(data => {
      if (data && data.order_list) {
        var order_list = data.order_list
        //遍历列表,并根据商品标题宽度给不同的订单项文本盒子添加不同的类样式
        order_list.forEach(item=>{
          var textWidth = self.getTextWidth(item.goods_name)
          if (textWidth>251){
            //多行展示
            item.titleStyle ="ellipsis_mul "  
          }else{       
            //单行展示     
            item.titleStyle = "ellipsis" 
          }
        })
        self.setData({
          orderList: data.order_list
        })
      }
    })
  },

样式部分,图片和文本盒子采用的是float定位,文本垂直方向的位置主要是通过padding和margin来调整:

.good_img {
  width: 204rpx;
  height: 204rpx;
  margin: 8rpx 20rpx;
  float: left;
}

.good_info {
  width:430rpx;
  float: right;
  overflow: hidden;
  padding:39rpx 16rpx 39rpx 0;
}
.good_name.ellipsis{
  margin-top:20rpx;
}

.good_name {
  font-size: 32rpx;
  line-height:42rpx;
  margin-bottom:12rpx;
  word-break:break-all;/*数字字母换行*/
}

注:第二种方法比较麻烦,需要获取单个不同字符所占的宽度,然后计算文本所占总宽度,再根据总宽度与盒子宽度进行对比,然后再根据不同的比较结果进行样式微调,以此实现垂直居中。该方法是非正规的方法的,需要进行大量的验证求证和计算,代码量多了不少,对页面渲染也有一定影响。原则上不建议使用,但是感兴趣的可以研究下,说不定以后就用到了呢。

扩展——使用vertical-align:middle实现不限行数全展示垂直居中

前边说的都是商品标题限定显示行数,在一些列表类的界面布局中,为了列表的美观,往往都是会限制某些文字显示的行数,以求所有列表显示的统一。但是对于某些列表没有没有下级详情页面或者对于一些详情页有此类布局的,大部分文本内容还是完全显示的好。

如上,虽然界面看起来有点不太美观,但有些时候还是很有必要的。

代码层面,可设计如下:

html:

<ul>
    <li>
        <img src="1.jpg"/>
        <div>
            <h3>商品标题不限字数完全展示</h3>
            <p>有效日期:2019年10月10日</p>
            <p>由此进入行使权益</p>
        </div>
    </li>
    <li>
        <img src="1.jpg"/>
        <div>
            <h3>商品标题不限字数完全展示</h3>
            <p>有效日期:2019年10月10日</p>
            <p>由此进入行使权益</p>
        </div>
    </li>
    ......
</ul>

css:

img{
    width: 1.3rem;
    height: 1.3rem;
    display: inline-block;
    vertical-align: middle;
}
div{
    width: 4.26rem;
    padding-left: .2rem;
    display: inline-block;
    vertical-align: middle;
}
......

需要注意的是,该方法不能使用弹性盒子以及float布局,只能在正常的盒子模型中使用行内元素(inline-block)。然后就是不需限制行数展示的文本设置好行高,不设置高度就好了。

使用弹性盒子布局:

如果弹性盒子用的比较好,那么使用弹性盒子实现这个也是挺简单的。

可以直接定义一个垂直居中的样式:

1 .vc_flex{display: -webkit-flex;display: flex;-webkit-align-items: center;align-items: center;}

给文本的父容器使用这个样式:

<view class="vc_flex"><view>商品名称,字数不限,可能一样,也可能2行,但是父容器高度固定</view></view>

如此,可以实现固定容器,不同行数文字的展示,

 

 同样,也可以针对前边的横向多个元素垂直居中布局。

原文地址:https://www.cnblogs.com/xyyt/p/10642818.html