多行展开收起效果的三种解决方案

2,371 阅读3分钟

1.第一种写法

<style>
        .content {
          display: flex;
        }
        .text {
            width: 475px;
            border: aqua solid 1px;
            color: #333;
            font-size: 14px;
        }
        .text.show::before{
          content: '';
          float: right;
          height: 100%;
          margin-bottom: 40px;
        }
        .text.show .btn {
            display: block;
        }
        .btn {
          color: dodgerblue;
          cursor: pointer;
          float: right;
          clear: both;
          margin-right: 8px;
          display: none;
        }

        .ellipsis {
            display: -webkit-box;
            overflow: hidden;
            -webkit-line-clamp: 3;
            -webkit-box-orient: vertical;
        }
        #exp {
            display: none;
        }
        #exp:checked+.ellipsis{
            display: flex;
        }
        .btn::after{
            content:'展开'
        }
        #exp:checked+.ellipsis .btn::after{
            content:'收起'
        }
        #exp:checked+.ellipsis .text::before{
          margin-bottom: -20px;
        }
</style>
<body>
    <input type="checkbox" id="exp" />
    <div class="content ellipsis">
        <div class="text">
          <label class="btn" for="exp"></label>
          <span>
            但听得蹄声如雷,十余乘马疾风般卷上山来。马上乘客一色都是玄色薄毡大氅,
     里面玄色布衣,但见人似虎,马如龙,人既矫捷,马亦雄骏,每一匹马都是高头
     长腿,通体黑毛,奔到近处,群雄眼前一亮,金光闪闪,却见每匹马的蹄铁竟然
     是黄金打就。来者一共是一十九骑,人数虽不甚多,气势之壮,却似有如千军万
     马一般,前面一十八骑奔到近处,拉马向两旁一分,最后一骑从中驰出</span>
        </div>
    </div>
    <script>
        function getLineHeight(el) {
            var temp = document.createElement(el.nodeName), ret;
            temp.setAttribute("style", "margin:0; padding:0; "
                + "font-family:" + (el.style.fontFamily || "inherit") + "; "
                + "font-size:" + (el.style.fontSize || "inherit"));
            temp.innerHTML = "A";

            el.parentNode.appendChild(temp);
            ret = temp.clientHeight;
            temp.parentNode.removeChild(temp);

            return ret;
        }
        let el = document.querySelector('.content')
        let text = document.querySelector('.text')
        if(Math.round(el.clientHeight / getLineHeight(el)) >= 3) {
            text.classList.add('show')
        }
    </script>
</body>

2.第二种写法

.wrapper {
  display: flex;
  margin: 50px auto;
  width: 800px;
  overflow: hidden;
/*   resize: horizontal; */
  border-radius: 8px;
  padding: 15px ;
  box-shadow: 20px 20px 60px #bebebe,
    -20px -20px 60px #ffffff;
}
.text {
  font-size: 20px;
  overflow: hidden;
  text-overflow: ellipsis;
  text-align: justify;
  /* display: flex; */
/*   display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical; */
  position: relative;
  line-height: 1.5;
  max-height: 4.5em;
  transition: .3s max-height;
}
.text::before {
  content: '';
  height: calc(100% - 26px);
  float: right;
}
.text::after {
  content: '';
  width: 999vw;
  height: 999vw;
  position: absolute;
  box-shadow: inset calc(100px - 999vw) calc(30px - 999vw) 0 0 #fff;
    margin-left: -100px;
}
.btn{
  position: relative;
  float: right;
  clear: both;
  margin-left: 20px;
  font-size: 16px;
  padding: 0 8px;
  background: #3F51B5;
  line-height: 24px;
  border-radius: 4px;
  color:  #fff;
  cursor: pointer;
  /* margin-top: -30px; */
}
.btn::after{
  content:'展开'
}
.exp{
  display: none;
}
.exp:checked+.text{
  max-height: none;
}
.exp:checked+.text::after{
  visibility: hidden;
}
.exp:checked+.text .btn::before{
  visibility: hidden;
}
.exp:checked+.text .btn::after{
  content:'收起'
}
.btn::before{
  content: '...';
  position: absolute;
  left: -5px;
  color: #333;
  transform: translateX(-100%)
}

<div class="wrapper">
  <input id="exp1" class="exp"  type="checkbox">
        <div class="text">
            <label class="btn" for="exp1"></label>
            浮动元素是如何定位的
正如我们前面提到的那样,当一个元素浮动之后,它会被移出正常的文档流,然后向左或者向右平移,一直平移直到碰到了所处的容器的边框,或者碰到另外一个浮动的元素。
在下面的图片中,有三个红色的正方形。其中有两个向左浮动,一个向右浮动。要注意到第二个向左浮动的正方形被放在第一个向左浮动的正方形的右边。如果还有更多的正方形这样浮动,它们会继续向右堆放,直到填满容器一整行,之后换行至下一行。
        </div>
    </div>

<div class="wrapper">
  <input id="exp2"  class="exp"  type="checkbox">
        <div class="text">
            
            <label class="btn" for="exp2"></label>
            浮动元素是如何定位的
正如我们前面提到的那样,当一个元素浮动之后,它会被移出正常的文档流,然后向左或者向右平移,一直平移直到碰到了所处的容器的边框,或者碰到另外一个浮动的元素。
        </div>
 </div>

3.第三种写法

<style>
    .container {
      padding: 50px;
    }

    .line-clamp {
      display: flex;
    }

    .line-clamp-content {
      max-height: 4.5em;
      line-height: 1.5;
      overflow: hidden;
      text-overflow: ellipsis;
      text-align: justify;
      position: relative;
    }

    .line-clamp-content::before {
      content: '';
      width: 0;
      float: right;
      height: calc(100% - 1.5em + 1px);
    }

    .line-clamp-content::after {
      content: '';
      position: absolute;
      width: 200vw;
      height: 100vh;
      box-shadow: inset -100vw calc(1.5em - 100vh) 0 0 #fff;
      margin-left: -100vw;
    }



    .line-clamp-btn {
      float: right;
      background-color: rgb(136, 110, 160);
      border-radius: 0.2em;
      padding: 0 0.2em;
      clear: both;
    }

    .line-clamp-btn>span {
      color: #fff;
    }

    .line-clamp-btn-open {
      margin-left: 1.3em;
      transform: translate(0, -1px);
      position: relative;
      cursor: pointer;
    }

    .line-clamp-btn-open::before {
      content: '...';
      transform: translate(-1.3em, 0);
      position: absolute;
    }

    .line-clamp-btn-close,
    .line-clamp-checkbox,
    .line-clamp-checkbox:checked+.line-clamp-content::before,
    .line-clamp-checkbox:checked+.line-clamp-content::after,
    .line-clamp-checkbox:checked+.line-clamp-content .line-clamp-btn-open {
      display: none;
    }

    .line-clamp-checkbox:checked+.line-clamp-content {
      max-height: inherit;
    }

    .line-clamp-checkbox:checked+.line-clamp-content .line-clamp-btn-close {
      display: inherit;
    }
</style>


<body>
  <div class="container">
    <h1>纯css实现展开和收起</h1>
    <div class="line-clamp">
      <input type="checkbox" class="line-clamp-checkbox" id="checkbox" />
      <div class="line-clamp-content">
        <label for="checkbox" class="line-clamp-btn line-clamp-btn-open">
          <span>展开</span>
        </label>
        主要利用 float:right CSS属性 指定元素应沿其容器的右侧放置,允许文本和内联元素环绕它。
        该元素从网页的正常流动(文档流)中移除,尽管仍然保持部分的流动性。
        然后利用另一个浮动元素把指定元素置于右下角,通过父容器
        display:flex(grid)的特性,flex项尺寸会根据内容自动计算,flex项子项可以使用百分比高度,获取到位置高度<code>calc(100% - 1.5em +1px)</code>
        加 1px 是为了避免计算出现小数高度不够。
        <label for="checkbox" class="line-clamp-btn line-clamp-btn-close">
          <span>收起</span>
        </label>
      </div>
    </div>
  </div>
</body>