【问题标题】:CSS Transition not working with white-space: nowrap and text-overflow: ellipsis when hoverCSS 过渡不适用于空白:nowrap 和文本溢出:悬停时省略号
【发布时间】:2020-01-02 06:26:15
【问题描述】:

我在一些文本中设置了white-space: nowraptext-overflow: ellipsis,当用户悬停时,它应该将空白值更改为正常值。悬停代码工作正常,但我无法使转换工作。

这是 CodePen 链接:https://codepen.io/anon/pen/qwYoyR

.App p {
  margin-bottom: 3px;
}
.App .bg-row {
  box-shadow: 0px 0px 5px #bdc3c7;
  background-color: #ecf0f1a3;
  padding: 20px;
  border-radius: 5px;
}
.App .bg-row .repositorios {
  transition: all 0.2s ease;
  margin-bottom: 20px;
}
.App .bg-row .repositorios:hover .repo-content {
  background-color: #d2d6d8;
  transition: 500ms ease-in-out;
}
.App .bg-row .repositorios .repo-image {
  width: 100%;
  height: auto;
  box-shadow: 0px 0px 5px #bdc3c7;
  -webkit-transition: all 0.2s ease;
  -moz-transition: all 0.2s ease;
  -o-transition: all 0.2s ease;
}
.App .bg-row .repositorios .repo-content {
  padding: 10px;
  transition: 500ms ease-in-out;
  overflow: hidden;
  box-shadow: 0px 0px 5px #bdc3c7;
  transition: 500ms ease-in-out;
  background-color: #ecf0f1;
}
.App .bg-row .repositorios .repo-content p {
  white-space: nowrap;
  text-overflow: ellipsis;
  overflow: hidden;
}
.App .bg-row .repositorios .repo-content .read-more {
  transition: 500ms ease-in-out;
  cursor: pointer;
}
.App .bg-row .repositorios .repo-content .read-more:hover {
  white-space: normal;
  transition: 500ms ease-in-out;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container App">
  <div class="row bg-row">
    <div class="col-sm-6 col-md-4 col-lg-3 repositorios">
      <div class="repo-content">
        <p class="read-more">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s</p>
      </div>
    </div>
  </div>
</div>

【问题讨论】:

  • 请记住,如果您询问如何在 CSS 中做某事,您应该展示 CSS 代码。当您询问如何在 Sass 中做某事(例如,您已经可以在 CSS 中做)时,应该提供 Sass 代码。
  • 另外,这里是animatable properties 的列表。很遗憾,您可能会注意到 white-spacetext-overflow 不在列表中。请参阅stackoverflow.com/questions/27904886/… 了解原因。

标签: html css css-transitions


【解决方案1】:

这些不是可以转换的属性。

white-space: nowrap;
text-overflow: ellipsis;

为了从一个属性过渡到另一个属性,CSS 需要中间值。 从 nowrap 到 normal 没有中间值,因为从 heright: 0 到 auto 或从 display: none 到 block 没有中间值。

使用 CSS 实现此目的的唯一方法是为您的元素使用 max-height,并在悬停时进行转换。然而,空白/省略号本身必须去 => 用与父级具有相同背景颜色的伪元素替换它们:

.x {
    position: relative;
    overflow: hidden;

    max-height: 20px;                /* set this to the height your first row would be */
    background-color: red;           /* you can change this, ofc */
    transition: max-height .5s;      /* the duration of the transition */
}
.x:after {
    content: '...';
    position: absolute;
    top: 0; right: 0;

    height: 1.5em;                   /* positioning it in line with the text - hacky */
    padding: 0 .2em;
    background-color: red;           /* keep the same as parent - it cannot be transparent unfortunately */

    opacity: 1;
    transition: opacity 0s .5s;      /* will delay the appearance of the '...' until the expanding transition has finished */
}
.x:hover {
    max-height: 1000px;              /* can be lower to create smoother response time */
}
.x:hover::after {
    opacity: 0;
    transition: opacity 0s 0s;       /* will apply the appearance of the '...' when hovered */
}

Hacky,可改进,但仅使用 CSS。

【讨论】:

    【解决方案2】:

    CodePen example you can check

    您需要固定 col-sm-6 col-md-4 col-lg-3 = "100%" 的宽度,这样您才能获得答案

    <div class="container App">
        <div class="row bg-row">
          <div class="repositorios">
            <div class="repo-content">
              <p class="read-more">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s</p>
          </div>
      </div>
    </div>
    

    应用这个 CSS 它将为你工​​作

    .App {
      p {
        margin-bottom: 3px;
      }
      .bg-row {
        box-shadow: 0px 0px 5px #bdc3c7;
        background-color: #ecf0f1a3;
        padding: 20px;
        border-radius: 5px;
        .repositorios {
          transition: all 0.2s ease;
          margin-bottom: 20px;
          &:hover {
            .repo-content {
              background-color: #d2d6d8;
              transition: 500ms ease-in-out;
            }
          }
          .repo-image {
            width: 100%;
            height: auto;
            box-shadow: 0px 0px 5px #bdc3c7;
            -webkit-transition: all 0.2s ease;
            -moz-transition: all 0.2s ease;
            -o-transition: all 0.2s ease;
          }
          .repo-content {
            padding: 10px;
            transition: 500ms ease-in-out;
            overflow: hidden;
            box-shadow: 0px 0px 5px #bdc3c7;
            transition: 300ms ease-in-out;
            background-color: #ecf0f1;
            p {
              white-space: nowrap;
        text-overflow: ellipsis;
        overflow: hidden;
        width: 200px;
            }
            .read-more {
              transition: 500ms ease-in-out;
              cursor: pointer;
              &:hover {
                white-space: normal;
        transition: 300ms ease-in-out;
        width: 100%;
              }
            }
          }
        }
      }
    }
    

    【讨论】:

    • 操作不希望 width 100% 悬停,这看起来很糟糕,我尝试将其删除,之后您的代码将无法正常工作。为什么?
    • 垂直动画看起来很奇怪。有没有其他方法可以让它感觉更顺畅?
    【解决方案3】:

    问题是因为white-space 不是可动画化 属性。您可以为 max-height 属性设置动画 - 请参阅 updated codepen 和相关摘录:

     .read-more {
          transition: 500ms ease-in-out;
          cursor: pointer;
          max-height: 2em; /* added */
          &:hover {
            white-space: normal;
            max-height: 100vh; /* added */
            transition: 500ms ease-in-out;
          }
        }
    

    但是当hover关闭时,返回动画将不起作用,因为white-space: nowrap 破坏了它。


    这是一个 hacky 解决方案,它仅使用 max-height 进行 transition,省略号由 伪元素处理 - 请参阅下面的codepen 和 sn-p:

    .App p {
      margin-bottom: 3px;
    }
    .App .bg-row {
      box-shadow: 0px 0px 5px #bdc3c7;
      background-color: #ecf0f1a3;
      padding: 20px;
      border-radius: 5px;
    }
    .App .bg-row .repositorios {
      margin-bottom: 20px;
    }
    .App .bg-row .repositorios:hover .repo-content {
      background-color: #d2d6d8;
    }
    .App .bg-row .repositorios:hover .repo-content .read-more {
      transition: all 500ms ease-in-out;
      white-space: normal;
      max-height: 100vh;
    }
    .App .bg-row .repositorios:hover .repo-content .read-more:after {
      transition: all 0.5s linear;
      opacity: 0;
    }
    .App .bg-row .repositorios .repo-image {
      width: 100%;
      height: auto;
      box-shadow: 0px 0px 5px #bdc3c7;
    }
    .App .bg-row .repositorios .repo-content {
      padding: 10px;
      overflow: hidden;
      box-shadow: 0px 0px 5px #bdc3c7;
      background-color: #ecf0f1;
    }
    .App .bg-row .repositorios .repo-content p {
      overflow: hidden;
    }
    .App .bg-row .repositorios .repo-content .read-more {
      transition: all 500ms ease-in-out;
      text-align: justify;
      display: flex;
      cursor: pointer;
      max-height: 1.7em;
      /* added */
    }
    .App .bg-row .repositorios .repo-content .read-more:after {
      transition: all 0.5s linear;
      content: '...';
      opacity: 1;
    }
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css">
    
    <div class="container App">
        <div class="row bg-row">
          <div class="col-sm-6 col-md-4 col-lg-3 repositorios">
            <div class="repo-content">
              <p class="read-more">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s</p>
          </div>
    </div>
    </div>
      </div>

    【讨论】:

      【解决方案4】:

      我认为您不能仅使用 css 对其进行动画处理。要为高度设置动画,您需要明确设置它。我会尝试用js获取真实高度,限制高度,然后在悬停时应用js中的高度。

      【讨论】:

      • 我想这就是问题所在。我试图不用js
      【解决方案5】:

      或者你可以像codepen 那样使用 Jquery 来完成

      $('.repo-content').hover(function(e){
        $(this).animate({height: '100%'}, 100);
        $('.bg-row.row').animate({height: '100%'}, 500);
      },function(){
        $(this).animate({height: '50px'}, 500);
      });
      .App p {
        
      	 margin-bottom: 3px;
      }
       .App .bg-row {
         transition: 500ms ease-in-out;
      	 box-shadow: 0px 0px 5px #bdc3c7;
      	 background-color: #ecf0f1 a3;
      	 padding: 20px;
         z-index:99;
         height:100px;
      	 border-radius: 5px;
      }
       .App .bg-row .repositorios {
      	 transition: all 0.2s ease;
      	 margin-bottom: 20px;
      }
       .App .bg-row .repositorios:hover .repo-content {
      	 background-color: #d2d6d8;
      	 transition: 500ms ease-in-out;
      }
       .App .bg-row .repositorios .repo-image {
      	 width: 100%;
      	 height: auto;
      	 box-shadow: 0px 0px 5px #bdc3c7;
      	 -webkit-transition: all 0.2s ease;
      	 -moz-transition: all 0.2s ease;
      	 -o-transition: all 0.2s ease;
      }
       .App .bg-row .repositorios .repo-content {
      	 padding: 10px;
      	 overflow: hidden;
         height:50px;
      	 box-shadow: 0px 0px 5px #bdc3c7;
      	 background-color: #ecf0f1;
      }
       .App .bg-row .repositorios .repo-content p {
      	 text-overflow: ellipsis;
      	 overflow: hidden;
       
      }
       .App .bg-row .repositorios .repo-content .read-more {
      	 transition: 500ms ease-in-out;
      	 cursor: pointer;
         z-index:99;
      }
       .App .bg-row .repositorios .repo-content .read-more:hover {
      	 
      	 transition: 500ms ease-in-out;
      }
      <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet"/>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
      <div class="container App">
          <div class="row bg-row">
            <div class="col-sm-6 col-md-4 col-lg-3 repositorios">
              <div class="repo-content">
                <p class="read-more">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s</p>
            </div>
      </div>
      </div>
        </div>

      顺便说一句,我不知道 scss,所以我将你的 scss 转换为 css,对此我深表歉意。

      【讨论】:

        【解决方案6】:

        这可以通过height: auto 实现,但CSS transition 需要高度固定值。但是你可以通过使用 jQuery 来解决这个问题。我只是写了一个基本的mouseentermouseleave 方法和一些逻辑来获取内容展开/折叠高度。所有提到的更改都应用于以下代码,您还可以查看工作小提琴。我希望它会帮助你。谢谢

        工作小提琴示例 - https://jsfiddle.net/creative_sid5/bgpus3q6/42/

        var rm = $('.read-more');   
        var rmInitialHeight = 0;
        var rmExpandedHeight = rm.outerHeight() + 'px';
        rm.removeClass('active');
        setTimeout(function(){
          rmInitialHeight = rm.outerHeight() + 'px';
          rm.height(rmInitialHeight);
        }, 500)
        rm.mouseenter(function() {	    		
          toggle(rmExpandedHeight);
        });
        rm.mouseleave(function() {	    		
          toggle(rmInitialHeight);
        })  
        
        function toggle(h) {
          rm.toggleClass('active').css('height', h);
        }
        .App p {
          margin-bottom: 3px; }
        
        .App .bg-row {
          box-shadow: 0px 0px 5px #bdc3c7;
          background-color: #ecf0f1a3;
          padding: 20px;
          border-radius: 5px; }
          .App .bg-row .repositorios {
            transition: all 0.2s ease;
            margin-bottom: 20px; }
            .App .bg-row .repositorios:hover .repo-content {
              background-color: #d2d6d8;
              transition: 500ms ease-in-out; }
            .App .bg-row .repositorios .repo-image {
              width: 100%;
              height: auto;
              box-shadow: 0px 0px 5px #bdc3c7;
              -webkit-transition: all 0.2s ease;
              -moz-transition: all 0.2s ease;
              -o-transition: all 0.2s ease; }
            .App .bg-row .repositorios .repo-content {
              padding: 10px;
              transition: 500ms ease-in-out;
              overflow: hidden;
              box-shadow: 0px 0px 5px #bdc3c7;
              transition: 500ms ease-in-out;
              background-color: #ecf0f1; }
              .App .bg-row .repositorios .repo-content .read-more {
                transition: 500ms ease-in-out;
                cursor: pointer;
                white-space: nowrap;
                text-overflow: ellipsis;
                overflow: hidden; }
              .App .bg-row .repositorios .repo-content .active {
                white-space: normal; }
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
        
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
        
        <div class="container App">
          <div class="row bg-row">
            <div class="col-sm-6 col-md-4 col-lg-3 repositorios">
              <div class="repo-content">
                <p class="read-more active">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s</p>
              </div>
            </div>
          </div>
        </div>

        【讨论】:

          【解决方案7】:

          我在这里有一个使用 React 和 CSS 的示例,但是您可以在纯 JS 或您选择的框架中实现相同的效果。 这里的关键是测量元素展开(隐藏,克隆)高度和折叠高度,然后通过 CSS 过渡处理动画。

          import React, { useState } from "react";
          
          const ShowMore = ({ text }) => {
            const [isOpen, toggle] = useState(false);
            const [
              isOnGoingCollapseTransition,
              setisOnGoingCollapseTransition
            ] = useState(false);
            const [initialHeight, setInitialHeight] = useState(0);
            const ref = React.useRef();
            const measureRef = React.useRef();
            React.useLayoutEffect(() => {
              setInitialHeight(ref.current.getBoundingClientRect().height);
            }, []);
            const onTransitionEnd = () => {
              if (isOpen) {
                setisOnGoingCollapseTransition(true);
              } else {
                setisOnGoingCollapseTransition(false);
              }
            };
            return (
              <div className="relative">
                <div className="absolute hidden" ref={measureRef}>
                  {text}
                </div>
                <div
                  onTransitionEnd={onTransitionEnd}
                  className="overflow-hidden transition"
                  style={{
                    height: isOpen
                      ? measureRef.current.getBoundingClientRect().height
                      : initialHeight
                  }}
                >
                  <div
                    ref={ref}
                    className={
                      !isOpen && !isOnGoingCollapseTransition ? "overflow-ellipsis" : ""
                    }
                  >
                    {text}
                  </div>
                </div>
                <span className="text-blue" onClick={() => toggle(open => !open)}>
                  {isOpen ? <span>show less</span> : <span>show more</span>}
                </span>
              </div>
            );
          };
          
          export default ShowMore;
          

          CSS:

              .relative{
                position: relative;
              }
              .absolute{
                position: absolute;
              }
              .overflow-ellipsis{
                white-space: nowrap;
                  overflow: hidden;
                  text-overflow: ellipsis;
              }
              .overflow-hidden{
                overflow: hidden;
              }
              .text-blue{
                color: blue;
                cursor: pointer;
              }
              .transition{
                transition: 225ms height linear;
              }
              .hidden{
                transform: translate(1000px);
              }
          

          查看这个工作示例Ellipsis collapse transition

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-12-06
            • 2016-02-15
            • 2017-04-09
            • 2016-11-15
            • 2012-04-13
            • 2013-07-20
            • 2018-02-03
            相关资源
            最近更新 更多