css webkit-line-clamp:文本对齐:right; breaks text-overflow:省略;

p4rjhz4m  于 2023-08-09  发布在  其他
关注(0)|答案(7)|浏览(102)

我的目标是:
1.限制文本行数
1.文本应右对齐
1.文本溢出:3个点
当我将text-align: right;添加到样式时,问题就开始了:3点的行为与没有text-align样式属性时的行为不同:通常,3个点在文本容器之外(灰色)。
x1c 0d1x的数据

**比较“好”与“坏”风格;**唯一的区别:“good”不包含text-align: right;样式属性。尝试在这些样式中使用font-size,你会发现对于“好”样式,3个点总是在文本容器内(灰色背景),而对于“坏”样式,3个点的位置是意外的(可能在容器内,或部分在容器内,或完全在容器外)

那么,* 有没有可能像“好”样式一样有3个点的行为,但同时让文本正确对齐?***考虑到行数限制。

* {
  box-sizing: border-box;
}

body {
  height: 100vh;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #78b9f3;
  margin:0;
  font-family: "Arial";
}

.wrapper {
  display: flex;
  justify-content: center;
}

.card {
  background: #fff;
  box-shadow: 0 4px 24px 3px rgb(0 0 0 / 10%);
  padding: 20px;
  margin: 20px;
  width: 200px;
  height: auto;
  border-radius: 6px;
}

p {
  font-size: 1em;
  line-height: 1.3em;
  margin:0;
}

h2 {
  font-size: 1.5em;
  margin: 0 0 0.5em 0;
}

.good {
  font-size: 20px;
  background-color: grey;
   text-overflow: ellipsis;
   display: -webkit-box;
   -webkit-line-clamp: 2;
           line-clamp: 2; 
   -webkit-box-orient: vertical;
}

.bad {
  font-size: 20px;
  text-align: right;
  background-color: grey;
   text-overflow: ellipsis;
   display: -webkit-box;
   -webkit-line-clamp: 2;
           line-clamp: 2; 
   -webkit-box-orient: vertical;
}

个字符

iugsix8n

iugsix8n1#

TL;DR:没有100%可预测的css修复

只要看看mdn上的兼容性表除了firefox,浏览器的支持是相当参差不齐的(说得委婉些)。
但是,您可以使用一些JavaScript来修复此呈现问题。
...或者你也可以mimictext-overflow an line-clamp properties with some old school overflow and line height properties.

示例一:css only hack

这个技巧是基于定义一些line-height相关的类。
CSS变量有助于简化计算:

:root {
  --overflowLineHeight: 1.25em;
  --overflowColor1: rgba(255, 255, 255, 1);
  --overflowColor2: rgba(255, 255, 255, 0);
}

.maxLines2 {
  max-height: calc(var(--overflowLineHeight) * 2);
}

字符串
实际的溢出指示符(省略号)元素只是一个具有背景渐变的绝对定位伪元素(放置在相对定位的父元素中)。

* {
  box-sizing: border-box;
}

body {
  height: 100vh;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #78b9f3;
  margin: 0;
  font-family: "Arial";
}

.wrapper {
  display: flex;
  justify-content: center;
  padding:1em;
}

.card {
  background: #fff;
  box-shadow: 0 4px 24px 3px rgb(0 0 0 / 10%);
  padding: 1em;
  margin: 1em;
  width: 33%;
  height: auto;
  border-radius: 6px;
  resize: both;
  overflow: hidden;
}

p {
  font-size: 1em;
  line-height: 1.3em;
  margin: 0;
}

h2 {
  font-size: 1.5em;
  margin: 0 0 0.5em 0;
}

:root {
  --overflowLineHeight: 1.25em;
  --overflowColor1: rgba(255, 255, 255, 1);
  --overflowColor2: rgba(255, 255, 255, 0);
}

.overflow {
  font-size: 20px;
  line-height: var(--overflowLineHeight);
  text-align: right;
  overflow: hidden;
  position: relative;
}

.overflow:after {
  content: " …";
  position: absolute;
  bottom: 0;
  right: 0;
  display: block;
  z-index: 1;
  background-image: linear-gradient( 90deg, var(--overflowColor2), var(--overflowColor1) 50%);
  width: 2.5em;
}

.maxLines2 {
  max-height: calc(var(--overflowLineHeight) * 2);
}

.maxLines3 {
  max-height: calc(var(--overflowLineHeight) * 3);
}

.maxLines4 {
  max-height: calc(var(--overflowLineHeight) * 4);
}
<section class="wrapper">
  <div class="card">
    <h2>Fix: 2 lines</h2>
    <p class=" maxLines2 overflow">Hello, I'm a very long text1 for at least three lines! Hello, I'm a very long text2 for at least three lines!</p>
  </div>

  <div class="card">
    <h2>Fix: 3 lines</h2>
    <p class=" maxLines3 overflow">Hello, I'm a very long text1 for at least three lines! Hello, I'm a very long text2 for at least three lines!</p>
  </div>

  <div class="card">
    <h2>Fix: 4 lines</h2>
    <p class=" maxLines4 overflow">Hello, I'm a very long text1 for at least three lines! Hello, I'm a very long text2 for at least three lines!</p>
  </div>

</section>

的数据

示例二:js hack for line-clamp

这个技巧是基于word-break: break-all将在块边界内呈现省略号的事实。
不幸的是,这将导致丑陋的断字。
要解决此问题,

  • 我们将所有单词拆分为<span>元素的数组。
  • 然后我们检查所有跨度高度:如果跨度高度大于第一个示例-它包含换行符
  • 带有换行符的span获取一个具有word-break: break-word属性的特殊类
let overflows = document.querySelectorAll(".overflow");
fixOverflow(overflows);

function fixOverflow(overflows) {
  overflows.forEach(function(text, i) {
    //split textContent into array
    let words = text.innerHTML
      .split(" ")
      .map((w) => {
        return w.trim();
      })
      .filter(Boolean);

    //delete current textContent
    let wrapped = "";
    text.textContent = "";
    text.style.setProperty("word-break", "break-all");
    let bbText = text.getBoundingClientRect();
    let bottomText = bbText.y + bbText.height;

    //get line height by checking the first word's height
    let span0 = document.createElement("span");
    span0.textContent = words[0] + " ";
    span0.classList.add("wordWrp");
    text.appendChild(span0);
    let height0 = span0.getBoundingClientRect().height;

    //check max lines and init counter
    let style = window.getComputedStyle(text);
    let maxLines = parseFloat(style.webkitLineClamp);
    let breaks = 0;

    //wrap words in spans
    for (let i = 1; i < words.length; i++) {
      let word = words[i];
      let span = document.createElement("span");
      span.textContent = word + " ";
      span.classList.add("wordWrp");
      text.appendChild(span);
      let bbSpan = span.getBoundingClientRect();
      let heightSpan = bbSpan.height;
      let bottomSpan = bbSpan.y + bbSpan.height;
      if (heightSpan > height0 && breaks < maxLines - 1 && bottomSpan < bottomText) {
        span.classList.add("wordWrpLine");
        breaks++;
      }
    }
  });
}

//update on resize 
const resizeObserver = new ResizeObserver(() => {
  upDateOverflows();
});
overflows.forEach(function(text, i) {
  resizeObserver.observe(text);
});

function upDateOverflows() {
  overflows.forEach(function(text, i) {
    let wordWraps = text.querySelectorAll(".wordWrp");
    let bbText = text.getBoundingClientRect();
    let bottom = bbText.y + bbText.height;
    let height0 = wordWraps[0].getBoundingClientRect().height;

    //check max lines and init counter
    let style = window.getComputedStyle(text);
    let maxLines = parseFloat(style.webkitLineClamp);
    let breaks = 0;

    for (let i = 1; i < wordWraps.length; i++) {
      let wordWrap = wordWraps[i];
      wordWrap.classList.remove("wordWrpLine");

      let bb = wordWrap.getBoundingClientRect();
      let height = bb.height;
      let bottomSpan = bb.y + bb.height;

      if (height > height0 && breaks < maxLines - 1 && bottomSpan < bottom) {
        wordWrap.classList.add("wordWrpLine");
        breaks++;
      }
    }
  });
}
* {
  box-sizing: border-box;
}

body {
  height: 100vh;
  width: 100%;
  background: #78b9f3;
  margin: 0;
  font-family: "Arial";
}

.wrapper {
  display: flex;
  justify-content: center;
  align-items: center;
}

.card {
  background: #fff;
  box-shadow: 0 4px 24px 3px rgb(0 0 0 / 10%);
  padding: 20px;
  margin: 20px;
  width: 250px;
  height: auto;
  border-radius: 6px;
  resize: both;
  overflow: hidden;
}

p {
  font-size: 1em;
  line-height: 1.3em;
  margin: 0;
}

h2 {
  font-size: 1.5em;
  margin: 0 0 0.5em 0;
}

.overflow {
  font-size: 20px;
  text-align: right;
  background-color: grey;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
}

.overflow:hover .wordWrp {
  outline: 1px solid red;
}

.maxLines2 {
  -webkit-line-clamp: 2;
  line-clamp: 2;
}

.maxLines3 {
  -webkit-line-clamp: 3;
  line-clamp: 3;
}

.maxLines4 {
  -webkit-line-clamp: 4;
  line-clamp: 4;
}

.wordWrpLine {
  word-break: break-word;
}

.wordWrpLine2 {
  background: red;
}
<h2>Resize cards</h2>
<section class="wrapper">
  <div class="card">
    <h2>Fix: 2 lines</h2>
    <p class=" maxLines2 overflow">Hello, I'm a very long text1 for at least three lines! Hello, I'm a very long text2 for at least three lines!</p>
  </div>

  <div class="card">
    <h2>Fix: 3 lines</h2>
    <p class=" maxLines3 overflow">Hello, I'm a very long text1 for at least three lines! Hello, I'm a very long text2 for at least three lines!</p>
  </div>
  
  <div class="card">
    <h2>Fix: 4 lines</h2>
    <p class=" maxLines4 overflow">Hello, I'm a very long text1 for at least three lines! Hello, I'm a very long text2 for at least three lines!</p>
  </div>
  
</section>

示例三:js hack仿真线夹

非常类似于前面的js方法-通过将元素的文本拆分为span元素。
这一次,我们通过附加一个自定义的<span>元素来完全替换css elllipsis占位符。
溢出的“省略号”占位符根据一些边界框检查放置:离开溢出定义边界的第一个跨度元素将是用于前置省略跨度的位置/索引。

let overflows = document.querySelectorAll(".overflow");
fixOverflow(overflows);

function fixOverflow(overflows) {
  overflows.forEach(function(text) {
    let spanWrps = text.querySelectorAll(".wordWrp");
    let words = '';
    let hasSpans = spanWrps.length ? true : false;
    let spanEllipse = text.querySelector(".spanEllipse");

    //create ellpse san if not already present
    if (!spanEllipse) {
      spanEllipse = document.createElement("span");
      spanEllipse.classList.add('spanEllipse');
      spanEllipse.textContent = ' …';
    }

    // get word/string array - unless it's aleady generated
    if (hasSpans) {
      words = [...spanWrps].map((word) => {
        return word.textContent
      });
    } else {
      //split textContent into array
      words = text.innerHTML
        .split(" ")
        .map((w) => {
          return w.trim();
        })
        .filter(Boolean);
    }

    let bbText = text.getBoundingClientRect();
    let bottomText = bbText.y + bbText.height;

    //delete current textContent
    if (!hasSpans) {
      text.textContent = "";
    }

    for (let i = 0; i < words.length; i++) {
      let word = words[i];

      //wrap words in spans if not already done
      let span = '';
      if (hasSpans) {
        span = spanWrps[i];
        span.classList.remove('wordWrpOverflow');
      } else {
        span = document.createElement("span");
        span.textContent = word + " ";
        text.appendChild(span);
        span.classList.add("wordWrp");
      }

      let bbSpan = span.getBoundingClientRect();
      let bottomSpan = bbSpan.y + bbSpan.height;
      if (bottomSpan > bottomText) {
        span.classList.add("wordWrpOverflow");
      } else {
        span.classList.remove("wordWrpOverflow");
      }
    }

    let firstOverFlow = text.querySelector('.wordWrpOverflow');
    if (firstOverFlow) {
      let bbE = spanEllipse.getBoundingClientRect();
      let bottomE = bbE.y + bbE.height;
      let bbPrev = firstOverFlow.previousElementSibling.getBoundingClientRect();
      let bottomPrev = bbPrev.y + bbPrev.height;

      //add ellipsis before first overflow element
      if (bottomE > bottomText && bottomPrev < bottomText) {
        firstOverFlow.parentNode.insertBefore(spanEllipse, firstOverFlow.previousElementSibling);
      } else {
        // ellipsis might be in overflow area - traverse backwards
        if (bottomPrev > bottomText) {
          firstOverFlow.parentNode.insertBefore(spanEllipse, firstOverFlow.previousElementSibling.previousElementSibling);
        } else {
          firstOverFlow.parentNode.insertBefore(spanEllipse, firstOverFlow);
        }
      }
    }
    // no ellipsis neede - remove it!
    else {
      spanEllipse.remove();
    }
  });
}

//update on resize 
const resizeObserver = new ResizeObserver(() => {
  fixOverflow(overflows)
});
overflows.forEach(function(text, i) {
  resizeObserver.observe(text);
});
* {
  box-sizing: border-box;
}

body {
  height: 100vh;
  width: 100%;
  background: #78b9f3;
  margin: 0;
  font-family: "Arial";
}

.card {
  background: #fff;
  padding: 20px;
  margin: 20px;
  height: auto;
  border-radius: 6px;
  resize: both;
  overflow: auto;
}

p {
  font-size: 1em;
  line-height: 1.3em;
  margin: 0;
}

h2 {
  font-size: 1.5em;
  margin: 0 0 0.5em 0;
}

:root {
  --lineHeight: 1.2em;
}

.overflow {
  font-size: 20px;
  line-height: var(--lineHeight);
  text-align: right;
  overflow: hidden;
}

.maxLines2 {
  max-height: calc(2 * var(--lineHeight));
}

.maxLines3 {
  max-height: calc(3 * var(--lineHeight));
}

.maxLines4 {
  max-height: calc(4 * var(--lineHeight));
}

.wordWrpOverflow {
  visibility: hidden;
}

/* force line break */

.spanEllipse+span {
  display: block
}

.txt-cnt * {
  text-align: center;
}

@media (min-width:720px) {
  .card {
    width: 33%;
  }
  .wrapper {
    display: flex;
    justify-content: center;
  }
}

@media (min-width:1024px) {
  .card {
    width: 250px;
  }
}
<section class="wrapper">

  <div class="card">
    <h2>Fix: 2 lines</h2>
    <p class=" maxLines2 overflow">Hello, I'm a very long text1 for at least three lines! Hello, I'm a very long text2 for at least three lines!</p>
  </div>

  <div class="card">
    <h2>Fix: 3 lines</h2>
    <p class=" maxLines3 overflow">Hello, I'm a very long text1 for at least three lines! Hello, I'm a very long text2 for at least three lines!</p>
  </div>

  <div class="card txt-cnt">
    <h2>Fix: 4 lines: <br />text-align:center</h2>
    <p class=" maxLines4 overflow">Hello, I'm a very long text1 for at least three lines! Hello, I'm a very long text2 for at least three lines!</p>
  </div>

</section>

排除支持text-overflow/line-clamp的浏览器

目前,只有firefox和一些iOS safari版本似乎可以正确渲染省略号。
为了避免这些浏览器不必要的js处理,您可以包含一个功能检测:

let firefoxOverflow = CSS.supports("text-overflow", "ellipsis ellipsis");
let safariWebkit = CSS.supports("-webkit-hyphens", "none");
let needsWorkaround = false;
if(!firefoxOverflow && !safariWebkit) {
  needsWorkaround = true;
  document.body.classList.add("needs-overflow-fix");
}


当然,这并不适用于所有的firefox和safari版本。
至少它不使用任何浏览器嗅探。

/**
 * check proper overflow support
 **/
let supportText = "";
let firefoxOverflow = CSS.supports("text-overflow", "ellipsis ellipsis");
let safariWebkit = CSS.supports("-webkit-hyphens", "none");
let needsWorkaround = false;
if (!firefoxOverflow && !safariWebkit) {
  needsWorkaround = true;
  document.body.classList.add("needs-overflow-fix");
}

// just for display
if (needsWorkaround) {
  supportText = "needs workaround - use js";
} else {
  supportText = "proper support – use css";
}
support.textContent = supportText;

/**
* apply workaround if necessary
**/
if (needsWorkaround) {
  let overflows = document.querySelectorAll(".overflow");
  fixOverflow(overflows);

  function fixOverflow(overflows) {
    overflows.forEach(function (text) {
      
      /*
      let style = window.getComputedStyle(text);
      let styleClamp = parseFloat(style.getPropertyValue("-webkit-line-clamp"));
      styleClamp = !styleClamp
        ? parseFloat(style.getPropertyValue("line-clamp"))
        : styleClamp;
      //console.log(style)
      console.log("clamp", styleClamp);

      if (styleClamp > 0) {
        //text.classList.add('maxLines'+styleClamp);
      }
      */

      let spanWrps = text.querySelectorAll(".wordWrp");
      let words = "";
      let hasSpans = spanWrps.length ? true : false;
      let spanEllipse = text.querySelector(".spanEllipse");

      //create ellpse san if not already present
      if (!spanEllipse) {
        spanEllipse = document.createElement("span");
        spanEllipse.classList.add("spanEllipse");
        spanEllipse.textContent = " …";
      }

      // get word/string array - unless it's aleady generated
      if (hasSpans) {
        words = [...spanWrps].map((word) => {
          return word.textContent;
        });
      } else {
        //split textContent into array
        words = text.innerHTML
          .split(" ")
          .map((w) => {
            return w.trim();
          })
          .filter(Boolean);
      }

      let bbText = text.getBoundingClientRect();
      let bottomText = bbText.y + bbText.height;

      //delete current textContent
      if (!hasSpans) {
        text.textContent = "";
      }

      for (let i = 0; i < words.length; i++) {
        let word = words[i];

        //wrap words in spans if not already done
        let span = "";
        if (hasSpans) {
          span = spanWrps[i];
          span.classList.remove("wordWrpOverflow");
        } else {
          span = document.createElement("span");
          span.textContent = word + " ";
          text.appendChild(span);
          span.classList.add("wordWrp");
        }

        let bbSpan = span.getBoundingClientRect();
        let bottomSpan = bbSpan.y + bbSpan.height;
        if (bottomSpan > bottomText) {
          span.classList.add("wordWrpOverflow");
        } else {
          span.classList.remove("wordWrpOverflow");
        }
      }

      let firstOverFlow = text.querySelector(".wordWrpOverflow");
      if (firstOverFlow) {
        let bbE = spanEllipse.getBoundingClientRect();
        let bottomE = bbE.y + bbE.height;
        let bbPrev = firstOverFlow.previousElementSibling.getBoundingClientRect();
        let bottomPrev = bbPrev.y + bbPrev.height;

        //add ellipsis before first overflow element
        if (bottomE > bottomText && bottomPrev < bottomText) {
          firstOverFlow.parentNode.insertBefore(
            spanEllipse,
            firstOverFlow.previousElementSibling
          );
        } else {
          // ellipsis might be in overflow area - traverse backwards
          if (bottomPrev > bottomText) {
            firstOverFlow.parentNode.insertBefore(
              spanEllipse,
              firstOverFlow.previousElementSibling.previousElementSibling
            );
          } else {
            firstOverFlow.parentNode.insertBefore(spanEllipse, firstOverFlow);
          }
        }
      }
      // no ellipsis neede - remove it!
      else {
        spanEllipse.remove();
      }
    });
  }

  //update on resize
  const resizeObserver = new ResizeObserver(() => {
    fixOverflow(overflows);
  });
  overflows.forEach(function (text, i) {
    resizeObserver.observe(text);
  });
}
* {
  box-sizing: border-box;
}

body {
  height: 100vh;
  width: 100%;
  background: #78b9f3;
  margin: 0;
  font-family: "Arial";
}

.needs-overflow-fix {
  background: orange;
}

.card {
  background: #fff;
  padding: 20px;
  margin: 20px;
  height: auto;
  border-radius: 6px;
  resize: both;
  overflow: auto;
}

p {
  font-size: 1em;
  line-height: 1.3em;
  margin: 0;
}

h2 {
  font-size: 1.5em;
  margin: 0 0 0.5em 0;
}

:root {
  --lineHeight: 1.2em;
}

.overflow {
  font-size: 20px;
  line-height: var(--lineHeight);
  text-align: right;
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
}

.needs-overflow-fix .overflow {
  text-overflow: unset;
  overflow: hidden;
  display: block;
  -webkit-line-clamp: unset !important;
  line-clamp: unset !important;
  -webkit-box-orient: unset !important;
}

.maxLines2 {
  -webkit-line-clamp: 2;
  line-clamp: 2;
}

.maxLines3 {
  -webkit-line-clamp: 3;
  line-clamp: 3;
}

.maxLines4 {
  -webkit-line-clamp: 4;
  line-clamp: 4;
}

.needs-overflow-fix .maxLines2 {
  max-height: calc(2 * var(--lineHeight));
}
.needs-overflow-fix .maxLines3 {
  max-height: calc(3 * var(--lineHeight));
}
.needs-overflow-fix .maxLines4 {
  max-height: calc(4 * var(--lineHeight));
}

.wordWrpOverflow {
  visibility: hidden;
}

/* force line break */
.spanEllipse + span {
  display: block;
}

.txt-cnt * {
  text-align: center;
}

@media (min-width: 720px) {
  .card {
    width: 33%;
  }

  .wrapper {
    display: flex;
    justify-content: center;
  }
}
@media (min-width: 1024px) {
  .card {
    width: 250px;
  }
}
<p style="text-align:center"><strong id="support" >&nbsp;</strong></p>
<section class="wrapper">
  <div class="card">
    <h2>Fix: 2 lines</h2>
    <p class=" maxLines2 overflow">Hello, I'm a very long text1 for at least three lines! Hello, I'm a very long text2 for at least three lines!</p>
  </div>
  <div class="card">
    <h2>Fix: 3 lines</h2>
    <p class=" maxLines3 overflow">Hello, I'm a very long text1 for at least three lines! Hello, I'm a very long text2 for at least three lines!</p>
  </div>
  <div class="card txt-cnt">
    <h2>Fix: 4 lines: <br />text-align:center</h2>
    <p class="maxLines4 overflow">Hello, I'm a very long text1 for at least three lines! Hello, I'm a very long text2 for at least three lines! Hello, I'm a very long text2 for at least three lines!</p>
  </div>

</section>

如果背景颜色从蓝色变为橙子-则应用js修复。

oxiaedzo

oxiaedzo2#

**演示:**去年6月,我创建了一个小教程,比较了Codepen上的水平省略号和垂直线箝位,包括响应式大小调整和间距调整,以及一些你可以玩的滑块。演示中的内联JS仅用于控制 * 自定义变量 *,与您的问题无关。我为你的目的添加了text-align收音机。
**解决方案:**将我的代码与您的代码进行比较,我认为您只需将您的text-overflow: ellipsis;(用于“好”或“坏”)更改为overflow: hidden,根据需要设置您的text-align,然后就可以开始了。

direction属性的值仅与text-align的值相关。例如:

  • body[dir="ltr"] p { text-align: right }
  • body[dir="rtl"] p { text-align: left }

但这是html文档的常见做法,似乎不是这里的问题。
下面的片段显示了使用 custom attributeline-clamp启动和运行所需的纯CSS,您可以将其用于任何需要行箝位的元素。
如果你需要更详细的解释,请在评论中告诉我。

[line-clamp] {
  /* Alternative character not supported
     by Edge/Chrome and line-clamp */

/* All [MANDATORY] for vertical line clamp */
  width: 100%;
  overflow: hidden;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;

}

.test {
  text-align: right
}

个字符

mwkjh3gx

mwkjh3gx3#

我找到了一个解决上述问题的方法:
1.为div/p添加padding-right:20 px-->该数字为只显示三个点的硬编码
1.使用text-align:右
希望这种方式可以帮助您暂时解决这个问题。

  • 见下例:*
* {
  box-sizing: border-box;
}

body {
  height: 100vh;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #78b9f3;
  margin:0;
  font-family: "Arial";
}

.wrapper {
  display: flex;
  justify-content: center;
}

.card {
  background: #fff;
  box-shadow: 0 4px 24px 3px rgb(0 0 0 / 10%);
  padding: 20px;
  margin: 20px;
  width: 200px;
  height: auto;
  border-radius: 6px;
}

p {
  font-size: 1em;
  line-height: 1.3em;
  margin:0;
}

h2 {
  font-size: 1.5em;
  margin: 0 0 0.5em 0;
}

.good {
  font-size: 20px;
  background-color: grey;
   text-overflow: ellipsis;
   display: -webkit-box;
   -webkit-line-clamp: 2;
           line-clamp: 2; 
   -webkit-box-orient: vertical;
   
   text-align: right;
   padding-right: 20px; //added code
  
}

.bad {
  font-size: 20px;
  text-align: right;
  background-color: grey;
   text-overflow: ellipsis;
   display: -webkit-box;
   -webkit-line-clamp: 2;
           line-clamp: 2; 
   -webkit-box-orient: vertical;
}

个字符

tyg4sfes

tyg4sfes4#

如上所述,基于 chrome 的浏览器并没有像预期的那样实现text-overflow: ellipsis;text-align: right;,因此JavaScript解决方案是不可避免的。
如果段落不包含HTML,而只包含文本(如您的示例所示),并且已知可能出现的空格字符(请参阅下面的getLinebreakPosis),则此答案有效。然而,在这个例子中,似乎只出现了平均的空格字符。
如果你处理的是很长的单词,那么你也需要添加一个断字库。

function exceedsHeight(element, height) {
  return parseFloat(getComputedStyle(element).height) > height
}

function refillParagraph(paragraph, maxHeight=42, endingString=' ...') {
// If text overflows maxHeight, cut it off and add an endingString.

  // If paragraph is not overflowing, do nothing and abort:
  if( ! exceedsHeight(paragraph, maxHeight) ) return

  // Otherwise store text and remove it of paragraph:
  const text = paragraph.textContent.trim()
  paragraph.textContent = ''

  // Refill paragraph character by character, plus the endingString:
  for(let i=0; i < text.length; i++) {
    paragraph.textContent = text.slice(0, i) + endingString

    // Paragraph overflows:
    if(exceedsHeight(paragraph, maxHeight)) {

      // Remove last character and get breaking points:
      let posis = getLinebreakPosis( text.slice(0, i-1) )

      // Fill paragraph with text until last found breaking point,
      // plus the endingString:
      for(let j=0; j < posis.length; j++) {
        paragraph.textContent = text.slice(0, posis[j]) + endingString

        // No overflow, found breaking point, break posis-loop:
        if( ! exceedsHeight(paragraph, maxHeight) ) break
      }
      // We're done, break the for-each-character-of-text-loop:
      break
    }
  }
}

function getLinebreakPosis(text) {
  // Return array with all positions where a space occurs in the text.
  // Sort by last found first.
  const posis = []
  const spaceChars = [' ', '\n', '\t'] // and probably some more
  let i = text.length
  while(i > 0) {
    i--
    if(spaceChars.includes(text[i])) {
      posis.push(i)
    }
  }
  return posis
}

// For every found paragraph, execute refillParagraph:
document.addEventListener('DOMContentLoaded', eve => {
  document.querySelectorAll('p').forEach(p => refillParagraph(p) )
});
p {
  width: 200px;
  text-align: right;
}
<article>
  <h2>Ellipse all the browsers</h2>
  <p>
    This is a paragraph with a decent amount of text in it, for illustration purposes.
  </p>
  <p>
    This is another paragraph which could be filled with ancient latin texts, just to exclude the most of us.
  </p>
</article>
pengsaosao

pengsaosao5#

现在看来,这个问题只能在Chrome中重现。Firefox和Safari在多行钳制文本之后正确呈现...,即使使用text-align: right也是如此。只有Chrome以某种奇怪的“绝对定位”方式在包含元素之外呈现省略号。

我找到的Chrome解决方法是在clamped text元素上添加padding-right: 1em

p {
  width: 300px;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  overflow: hidden;
  text-align: right;
  padding-right: 1em; 
}

个字符

mtb9vblg

mtb9vblg6#

  • 您必须使用direction: rtl;将浏览器设置为更改方向。
  • text-align:right所以也将出现在右边,按照预期的行为。
* {
  box-sizing: border-box;
}

body {
  height: 100vh;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #78b9f3;
  margin: 0;
  font-family: "Arial";
}

.wrapper {
  display: flex;
  justify-content: center;
}

.card {
  background: #fff;
  box-shadow: 0 4px 24px 3px rgb(0 0 0 / 10%);
  padding: 20px;
  margin: 20px;
  width: 200px;
  height: auto;
  border-radius: 6px;
}

p {
  font-size: 1em;
  line-height: 1.3em;
  margin: 0;
}

h2 {
  font-size: 1.5em;
  margin: 0 0 0.5em 0;
}

.good {
  font-size: 20px;
  background-color: grey;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
}

.bad {
  font-size: 20px;
  text-align: right;
  background-color: grey;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  direction: rtl;
}

个字符

s6fujrry

s6fujrry7#

我已经添加了方向rtl坏类和点翻转,这是你所需要的。


的数据
还增加了溢出隐藏隐藏其余的文字。希望这对你有帮助。

相关问题