如果没有JavaScript,当较长的文本不适合时,我可以显示不同的文本吗?

时间:2022-07-13 21:12:36

What I'm trying to do

I have a size-limited box which is supposed to contain some text:

我有一个尺寸限制的盒子,应该包含一些文字:

.box {
  width: 100px;
  height: 40px;
  background-color: yellow;
}
<div class="box">
  Some text goes here.
</div>

However, if the text becomes too long to fit in the box, I want to replace that text with a different, shorter version, which I have prepared in advance.

但是,如果文本太长而无法放入框中,我想用不同的较短版本替换该文本,这是我事先准备好的。

So for example, if I want to populate two boxes with these two names:

例如,如果我想用这两个名称填充两个框:

Short version      Long version
------------------------------------------------------------
Rudolf E. Raspe    Rudolf Erich Raspe
Baron Munchausen   Hieronymus Karl Friedrich von Munchhausen

Then the first box will contain "Rudolf Erich Raspe" since it's short enough to fit inside, but the second box will contain "Baron Munchausen" since the Baron's full name is too long to fit.

然后第一个盒子将包含“Rudolf Erich Raspe”,因为它足够短以适应内部,但第二个盒子将包含“Baron Munchausen”,因为Baron的全名太长而不适合。

How can I set up such a box, using just HTML5 and CSS3? Browser compatibility is important but, I don't need to accommodate really old versions or Internet Explorer prior to 11.

如何使用HTML5和CSS3设置这样的盒子?浏览器兼容性很重要,但我不需要在11之前容纳真正的旧版本或Internet Explorer。

Alternatives

I can choose any of the standard options for handling too-long text - letting it overflow, or cutting it via overflow: hidden, or adding scrollbars, or adding ellipses, or any of the other standard solutions. But since I already have short versions of every possible text there, I would like to use these instead.

我可以选择任何标准选项来处理太长的文本 - 让它溢出,或通过溢​​出来切割:隐藏,或添加滚动条,或添加省略号,或任何其他标准解决方案。但由于我已经有了每个可能文本的简短版本,我想用它们代替。

I can do this in JavaScript by, for example, using a wrapper and comparing its size with the box's. But I would like a non-JavaScript solution, if possible.

我可以在JavaScript中执行此操作,例如,使用包装器并将其大小与盒子进行比较。但如果可能的话,我想要一个非JavaScript解决方案。

What I've tried

So far I thought about making the text somehow push itself down if it's too long (some combination of white-space and word-wrap?), making the container overflow: hidden to hide it when it's down there, and placing the short version of the text behind it, but I couldn't get it to work while still allowing the text to occupy more than one line.

到目前为止,我想过如果文本太长(白色空间和自动换行的某种组合?)会使文本以某种方式向下推动自己,使容器溢出:隐藏在它下面时隐藏它,并放置短版本它背后的文字,但我仍然无法让它工作,同时仍然允许文本占用多行。

Another approach is to place an element with the short text just below the element with the long text, and use some transform which makes that short element take over when it's pushed down too much... But I couldn't get it to work either.

另一种方法是在元素下面放置一个带有长文本的短文本元素,然后使用一些变换使得短元素在被过度推下时接管...但我无法使它工作。

So... any other ideas?

那么......还有其他想法吗?

6 个解决方案

#1


22  

There is a way... kinda...

有一种方式......有点......

.box {
  width: 100px;
  height: 18px;
  background-color: yellow;
  overflow: hidden;
  position: relative;
  margin-bottom: 20px;
}

span {  position: absolute; bottom: 0; left: 0; width: 100%; max-height: 36px;  }
em { position: absolute; width: 100%; top: 18px; left: 0; background-color: yellow; }
<div class="box">
   <span> 
     This text fits
     <em>fallback text</em>
   </span>
</div>

<div class="box">
   <span> 
     Huge text that doesn't fit and it's more than 3 lines. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
     <em>fallback text</em>
   </span>
</div>

<div class="box">
   <span> 
     This text doesn't fit
     <em>fallback text</em>
   </span>
</div>

It's not a very pretty solution, but hey it's something. :)

这不是一个非常漂亮的解决方案,但嘿,这是一些东西。 :)

#2


5  

I've done something similar by using overflow:hidden and floating divs.

我通过使用overflow:hidden和floating divs做了类似的事情。

<div style="overflow:hidden;height:1.2em;">
  <div style="float:left">Rudolph</div>
  <div style="float:right">Raspe</div>
  Erich
</div>

So, on a small block you'll get Rudolph Raspe, on a big - Rudolph Erich Raspe.

所以,在一个小街区,你会得到Rudolph Raspe,一个大的鲁道夫埃里希拉斯佩。

Obviously, it's not very universal, but in some specific cases it can be used.

显然,它不是很普遍,但在某些特定情况下可以使用它。

#3


3  

I was having some fun with a single-line solution, I realise the multi-line solution may be a better fit for the OP. I'm just sticking it up here in case it's useful to anyone. I ran a quick test on the latest versions of Firefox, Chrome, IE and Edge, and it seems to work fine everywhere. I've added some fixed width boxes to the example, but it actually works with a dynamic box width as well.

我对单线解决方案感到很开心,我意识到多线解决方案可能更适合OP。我只是坚持下去,以防它对任何人都有用。我对最新版本的Firefox,Chrome,IE和Edge进行了快速测试,似乎无处不在。我在示例中添加了一些固定宽度的框,但它实际上也适用于动态框宽度。

div {
  position: relative;
  overflow: hidden;
  line-height: 1.2em;
  height: 1.2em;
  /* extraneous CSS added for sample clarity only */
  font-family: Consolas,Menlo,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New,monospace,sans-serif;
  font-size: 13px;
  margin: 3px;  
}

div > span {
  background-color: #EFF0F1;
  float: left;
}

div::before {
  content: "\00a0";
}

div::after {
  content: attr(title);
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: -1;
  background-color: #EFF0F1;
}
<div title="Rudolf E. Raspe">
  <span>Rudolf Erich Raspe</span>
</div>
<div title="Baron Munchausen">
  <span>Hieronymus Karl Friedrich von Munchhausen</span>
</div>
<div title="Rudolf E. Raspe" style="width:400px;">
  <span>Rudolf Erich Raspe</span>
</div>
<div title="Baron Munchausen" style="width:400px;">
  <span>Hieronymus Karl Friedrich von Munchhausen</span>
</div>
<div title="Rudolf E. Raspe" style="width:200px;">
  <span>Rudolf Erich Raspe</span>
</div>
<div title="Baron Munchausen" style="width:200px;">
  <span>Hieronymus Karl Friedrich von Munchhausen</span>
</div>
<div title="Rudolf E. Raspe" style="width:120px;">
  <span>Rudolf Erich Raspe</span>
</div>
<div title="Baron Munchausen" style="width:120px;">
  <span>Hieronymus Karl Friedrich von Munchhausen</span>
</div>

It works by creating three elements inside a containing div.

它的工作原理是在包含div中创建三个元素。

  • An invisible div::before pseudo element with the single purpose of just being there to make sure the second element (the span) isn't the first element on the line
  • 一个不可见的div :: before伪元素,其唯一目的就是确保第二个元素(span)不是该行的第一个元素
  • A span containing the longer version of the text
  • 包含较长版本文本的范围
  • A div::after pseudo element containing the shorter version of the text
  • 包含较短版本文本的div :: after伪元素

The containing div is set to position: relative to create a new block formatting context inside itself.

包含div设置为position:relative以在其自身内创建新的块格式化上下文。

The div::after pseudo element is set to position: absolute with top: 0; left: 0; set to ensure it sits at the same position as the span, while right: 0; bottom: 0; ensure the element is always as large as its containing element (the div). z-index: -1; ensures the element sits behind the span.

div :: after伪元素设置为position:absolute with top:0;左:0;设置为确保它与跨度位于同一位置,而右:0;底部:0;确保元素始终与其包含元素(div)一样大。 z-index:-1;确保元素位于跨度后面。

Both the div::before and the span are rendered as inline elements. As soon as the div::before and the span together become too wide to fit snugly on one line, the whole span moves down to the next line, revealing the div::after which was hiding behind it.

div :: before和span都呈现为内联元素。一旦div :: before和span一起变得太宽而无法紧贴在一条线上,整个跨度就会向下移动到下一行,显示div ::之后隐藏在它后面。

The only reason for having the div::before there is to ensure the span moves down to the next line, it wouldn't do so if it was the first inline element.

使用div ::之前确保跨度向下移动到下一行的唯一原因是,如果它是第一个内联元素,则不会这样做。

The overflow: hidden; line-height: 1.2em; height: 1.2em; on the containing div ensure the span is invisible as soon as it jumps to the next line.

溢出:隐藏; line-height:1.2em;身高:1.2em;在包含div上确保跨度一旦跳到下一行就不可见。

#4


1  

Pure CSS Solution:

纯CSS解决方案:

Using:

使用:

<div class="box" data-shortname="Baron Munchausen">
    Hieronymus Karl Friedrich von Munchhausen
</div>

For ages I tried to do something using box::after and z-index:

多年来我尝试使用box :: after和z-index做一些事情:

box {
    position: relative;
    display: block;
    width: 120px;
    height: 40px;
    background-color: yellow;
    overflow: hidden;
    z-index: 0;
}

box::after {
    content: attr(data-shortname);
    position: absolute;
    display: block;
    top: 0;
    left: 0;
    background-color: yellow;
    z-index: 1;
}

I came up empty-handed - though you could use a @media query with the setup above to apply a positive or negative z-index to box::after.

我空手而归 - 虽然您可以使用带有上述设置的@media查询将正面或负面的z-index应用于box :: after。

(If the box::after z-index is positive, the shortname displays, otherwise the longer name displays.)

(如果z :: index之后的box :: yes,则显示短名称,否则显示更长的名称。)


JavaScript Solution:

JavaScript解决方案:

So here is a JavaScript-based solution using data-* after all:

所以这里有一个基于JavaScript的解决方案,毕竟使用data- *:

var boxes = document.getElementsByClassName('box');

for (var i = 0; i < boxes.length; i++) {
    if (boxes[i].textContent.length > 20) {
        boxes[i].textContent = boxes[i].dataset.shortname;
    }
}
.box {
    position: relative;
    width: 120px;
    height: 40px;
    background-color: yellow;
    margin-bottom: 12px;
}
<div class="box" data-shortname="Rudolf E. Raspe">
    Rudolf Erich Raspe
</div>

<div class="box" data-shortname="Baron Munchausen">
    Hieronymus Karl Friedrich von Munchhausen
</div>

#5


1  

I know it's not a true answer, but rather an alternative. Is there any reason you can't use text-overflow?

我知道这不是一个真正的答案,而是另一种选择。有什么理由你不能使用文本溢出?

.box span {
    text-overflow: ellipsis; 
    white-space: nowrap;
    overflow: hidden;
}

Helpful link:

有用的链接:

https://css-tricks.com/almanac/properties/t/text-overflow/

https://css-tricks.com/almanac/properties/t/text-overflow/

#6


0  

There are actually a lot of ways this 'could' be done if the sizes and patterns were constant...but in your example with the names, the short text is not even part of the long text in both cases, it's a different string entirely in the second example, which limits your options in terms of showing/hiding/overlapping

如果大小和模式是不变的,实际上有很多方法可以做到这一点......但是在你的名字示例中,短文本在两种情况下都不是长文本的一部分,它是一个不同的字符串完全在第二个例子中,它限制了你在显示/隐藏/重叠方面的选择

If you can identify a consistent screen size at which you are going to swap from short to long, you can use data- attributes and CSS content along with @media queries.

如果您可以确定要从短到长交换的一致屏幕大小,则可以使用数据属性和CSS内容以及@media查询。

Considering the variables, I would suggest using something like the example below to change all the items to the short version at a moderate breakpoint, and then use a method like adding an ellipsis to handle any longer values that would wrap in either short or long versions.

考虑到变量,我建议使用类似下面的示例在中等断点处将所有项目更改为短版本,然后使用添加省略号的方法来处理将包装在短版本或长版本中的任何更长的值。

<div class="box">
  <p class="text-container" data-short-version="Rudolf E. Raspe" data-long-version="Rudolf Erich Raspe"></p>
  <p class="text-container" data-short-version="Baron Munchausen" data-long-version="Hieronymus Karl Friedrich von Munchhausen"></p>
</div>

.text-container:before {
  content:attr(data-short-version);}

.text-container {  width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size:40px;
  margin:0px;}

@media screen and (min-width:600px) {
  .text-container:before {
    content:attr(data-long-version);
  }
}

Example here: http://codepen.io/ryantdecker/pen/wWPJNA

示例:http://codepen.io/ryantdecker/pen/wWPJNA

#1


22  

There is a way... kinda...

有一种方式......有点......

.box {
  width: 100px;
  height: 18px;
  background-color: yellow;
  overflow: hidden;
  position: relative;
  margin-bottom: 20px;
}

span {  position: absolute; bottom: 0; left: 0; width: 100%; max-height: 36px;  }
em { position: absolute; width: 100%; top: 18px; left: 0; background-color: yellow; }
<div class="box">
   <span> 
     This text fits
     <em>fallback text</em>
   </span>
</div>

<div class="box">
   <span> 
     Huge text that doesn't fit and it's more than 3 lines. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
     <em>fallback text</em>
   </span>
</div>

<div class="box">
   <span> 
     This text doesn't fit
     <em>fallback text</em>
   </span>
</div>

It's not a very pretty solution, but hey it's something. :)

这不是一个非常漂亮的解决方案,但嘿,这是一些东西。 :)

#2


5  

I've done something similar by using overflow:hidden and floating divs.

我通过使用overflow:hidden和floating divs做了类似的事情。

<div style="overflow:hidden;height:1.2em;">
  <div style="float:left">Rudolph</div>
  <div style="float:right">Raspe</div>
  Erich
</div>

So, on a small block you'll get Rudolph Raspe, on a big - Rudolph Erich Raspe.

所以,在一个小街区,你会得到Rudolph Raspe,一个大的鲁道夫埃里希拉斯佩。

Obviously, it's not very universal, but in some specific cases it can be used.

显然,它不是很普遍,但在某些特定情况下可以使用它。

#3


3  

I was having some fun with a single-line solution, I realise the multi-line solution may be a better fit for the OP. I'm just sticking it up here in case it's useful to anyone. I ran a quick test on the latest versions of Firefox, Chrome, IE and Edge, and it seems to work fine everywhere. I've added some fixed width boxes to the example, but it actually works with a dynamic box width as well.

我对单线解决方案感到很开心,我意识到多线解决方案可能更适合OP。我只是坚持下去,以防它对任何人都有用。我对最新版本的Firefox,Chrome,IE和Edge进行了快速测试,似乎无处不在。我在示例中添加了一些固定宽度的框,但它实际上也适用于动态框宽度。

div {
  position: relative;
  overflow: hidden;
  line-height: 1.2em;
  height: 1.2em;
  /* extraneous CSS added for sample clarity only */
  font-family: Consolas,Menlo,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New,monospace,sans-serif;
  font-size: 13px;
  margin: 3px;  
}

div > span {
  background-color: #EFF0F1;
  float: left;
}

div::before {
  content: "\00a0";
}

div::after {
  content: attr(title);
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: -1;
  background-color: #EFF0F1;
}
<div title="Rudolf E. Raspe">
  <span>Rudolf Erich Raspe</span>
</div>
<div title="Baron Munchausen">
  <span>Hieronymus Karl Friedrich von Munchhausen</span>
</div>
<div title="Rudolf E. Raspe" style="width:400px;">
  <span>Rudolf Erich Raspe</span>
</div>
<div title="Baron Munchausen" style="width:400px;">
  <span>Hieronymus Karl Friedrich von Munchhausen</span>
</div>
<div title="Rudolf E. Raspe" style="width:200px;">
  <span>Rudolf Erich Raspe</span>
</div>
<div title="Baron Munchausen" style="width:200px;">
  <span>Hieronymus Karl Friedrich von Munchhausen</span>
</div>
<div title="Rudolf E. Raspe" style="width:120px;">
  <span>Rudolf Erich Raspe</span>
</div>
<div title="Baron Munchausen" style="width:120px;">
  <span>Hieronymus Karl Friedrich von Munchhausen</span>
</div>

It works by creating three elements inside a containing div.

它的工作原理是在包含div中创建三个元素。

  • An invisible div::before pseudo element with the single purpose of just being there to make sure the second element (the span) isn't the first element on the line
  • 一个不可见的div :: before伪元素,其唯一目的就是确保第二个元素(span)不是该行的第一个元素
  • A span containing the longer version of the text
  • 包含较长版本文本的范围
  • A div::after pseudo element containing the shorter version of the text
  • 包含较短版本文本的div :: after伪元素

The containing div is set to position: relative to create a new block formatting context inside itself.

包含div设置为position:relative以在其自身内创建新的块格式化上下文。

The div::after pseudo element is set to position: absolute with top: 0; left: 0; set to ensure it sits at the same position as the span, while right: 0; bottom: 0; ensure the element is always as large as its containing element (the div). z-index: -1; ensures the element sits behind the span.

div :: after伪元素设置为position:absolute with top:0;左:0;设置为确保它与跨度位于同一位置,而右:0;底部:0;确保元素始终与其包含元素(div)一样大。 z-index:-1;确保元素位于跨度后面。

Both the div::before and the span are rendered as inline elements. As soon as the div::before and the span together become too wide to fit snugly on one line, the whole span moves down to the next line, revealing the div::after which was hiding behind it.

div :: before和span都呈现为内联元素。一旦div :: before和span一起变得太宽而无法紧贴在一条线上,整个跨度就会向下移动到下一行,显示div ::之后隐藏在它后面。

The only reason for having the div::before there is to ensure the span moves down to the next line, it wouldn't do so if it was the first inline element.

使用div ::之前确保跨度向下移动到下一行的唯一原因是,如果它是第一个内联元素,则不会这样做。

The overflow: hidden; line-height: 1.2em; height: 1.2em; on the containing div ensure the span is invisible as soon as it jumps to the next line.

溢出:隐藏; line-height:1.2em;身高:1.2em;在包含div上确保跨度一旦跳到下一行就不可见。

#4


1  

Pure CSS Solution:

纯CSS解决方案:

Using:

使用:

<div class="box" data-shortname="Baron Munchausen">
    Hieronymus Karl Friedrich von Munchhausen
</div>

For ages I tried to do something using box::after and z-index:

多年来我尝试使用box :: after和z-index做一些事情:

box {
    position: relative;
    display: block;
    width: 120px;
    height: 40px;
    background-color: yellow;
    overflow: hidden;
    z-index: 0;
}

box::after {
    content: attr(data-shortname);
    position: absolute;
    display: block;
    top: 0;
    left: 0;
    background-color: yellow;
    z-index: 1;
}

I came up empty-handed - though you could use a @media query with the setup above to apply a positive or negative z-index to box::after.

我空手而归 - 虽然您可以使用带有上述设置的@media查询将正面或负面的z-index应用于box :: after。

(If the box::after z-index is positive, the shortname displays, otherwise the longer name displays.)

(如果z :: index之后的box :: yes,则显示短名称,否则显示更长的名称。)


JavaScript Solution:

JavaScript解决方案:

So here is a JavaScript-based solution using data-* after all:

所以这里有一个基于JavaScript的解决方案,毕竟使用data- *:

var boxes = document.getElementsByClassName('box');

for (var i = 0; i < boxes.length; i++) {
    if (boxes[i].textContent.length > 20) {
        boxes[i].textContent = boxes[i].dataset.shortname;
    }
}
.box {
    position: relative;
    width: 120px;
    height: 40px;
    background-color: yellow;
    margin-bottom: 12px;
}
<div class="box" data-shortname="Rudolf E. Raspe">
    Rudolf Erich Raspe
</div>

<div class="box" data-shortname="Baron Munchausen">
    Hieronymus Karl Friedrich von Munchhausen
</div>

#5


1  

I know it's not a true answer, but rather an alternative. Is there any reason you can't use text-overflow?

我知道这不是一个真正的答案,而是另一种选择。有什么理由你不能使用文本溢出?

.box span {
    text-overflow: ellipsis; 
    white-space: nowrap;
    overflow: hidden;
}

Helpful link:

有用的链接:

https://css-tricks.com/almanac/properties/t/text-overflow/

https://css-tricks.com/almanac/properties/t/text-overflow/

#6


0  

There are actually a lot of ways this 'could' be done if the sizes and patterns were constant...but in your example with the names, the short text is not even part of the long text in both cases, it's a different string entirely in the second example, which limits your options in terms of showing/hiding/overlapping

如果大小和模式是不变的,实际上有很多方法可以做到这一点......但是在你的名字示例中,短文本在两种情况下都不是长文本的一部分,它是一个不同的字符串完全在第二个例子中,它限制了你在显示/隐藏/重叠方面的选择

If you can identify a consistent screen size at which you are going to swap from short to long, you can use data- attributes and CSS content along with @media queries.

如果您可以确定要从短到长交换的一致屏幕大小,则可以使用数据属性和CSS内容以及@media查询。

Considering the variables, I would suggest using something like the example below to change all the items to the short version at a moderate breakpoint, and then use a method like adding an ellipsis to handle any longer values that would wrap in either short or long versions.

考虑到变量,我建议使用类似下面的示例在中等断点处将所有项目更改为短版本,然后使用添加省略号的方法来处理将包装在短版本或长版本中的任何更长的值。

<div class="box">
  <p class="text-container" data-short-version="Rudolf E. Raspe" data-long-version="Rudolf Erich Raspe"></p>
  <p class="text-container" data-short-version="Baron Munchausen" data-long-version="Hieronymus Karl Friedrich von Munchhausen"></p>
</div>

.text-container:before {
  content:attr(data-short-version);}

.text-container {  width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size:40px;
  margin:0px;}

@media screen and (min-width:600px) {
  .text-container:before {
    content:attr(data-long-version);
  }
}

Example here: http://codepen.io/ryantdecker/pen/wWPJNA

示例:http://codepen.io/ryantdecker/pen/wWPJNA