2019-06-02
CSS crop string in the middle
stackoverflow
Question

I have a big filename that I'm cropping using css text-overflow: ellipsis.

<style>
   #fileName {
      width: 100px;
      white-space: nowrap;
      text-overflow: ellipsis;
      overflow: hidden;
  }
</style>
<div id="fileName"> This is the big name of my file.txt</div>

So I have this output

This is the bi...

But I want to preserve the file extension and have something like this

This is the... le.txt

Is it possible only using CSS?

Since my files are always txt, I've tried to use text-overflow: string, but it looks like it only works on Firefox:

 text-overflow: '*.txt';
Answer
1

Here is a clean CSS solution using the data-* attribute and two ::after pseudo-elements. I also added an optional hover and show all text (the #fileName::after pseudo element needs to be removed when the full text is shown).

Example 1

#fileName { 
  position: relative; 
  width: 100px; 
} 
 
#fileName p { 
  white-space: nowrap; 
  text-overflow: ellipsis; 
  overflow: hidden; 
} 
 
#fileName:after { 
  content: attr(data-filetype); 
  position: absolute; 
  left: 100%; 
  top: 0; 
} 
 
 
/*Show on hover*/ 
 
#fileName:hover { 
  width: auto 
} 
 
#fileName:hover:after { 
  display: none; 
}
<div id="fileName" data-filetype="txt"> 
  <p>This is the big name of my file.txt</p> 
</div>


Going further — hiding the appended filetype when the filename is short

The #fileName p::after is given a background color that matches the background of the text. This covers the ".txt" when the filenames are short and therefore not cut off with overflow: hidden.

Note the padding-right: 22px, this pushes the ".txt" beyond the ellipsis.

Refer to examples 2 and 3 below for different methods with different browser support for each. It doesn't seem to be possible to hide the ".txt" happily in all browsers.

Example 2

Browser Compatibility: Chrome and Firefox.

The #fileName p::after is given a background color that matches the background of the text. This covers the ".txt" when the filenames are short and therefore not cut off with overflow: hidden.

Note the padding-right on each of the ::after pseudo-elements. padding-right: 22px pushes the ".txt" beyond the ellipsis and padding-right: 100% gives the covering pseudo-element its width. The padding-right: 100% doesn't work with Edge or IE 11.

#fileName { 
  position: relative; 
  width: 122px; 
} 
 
#fileName::after { 
  content: attr(data-filetype); 
  position: absolute; 
  right: 0; 
  top: 0; 
} 
 
#fileName p { 
  white-space: nowrap; 
  text-overflow: ellipsis; 
  overflow: hidden; 
  padding-right: 22px; 
} 
 
#fileName p::after { 
  content: ''; 
  background: #FFF; 
  position: relative; 
  padding-right: 100%; 
  z-index: 1; 
} 
 
/*Show on hover*/ 
 
#fileName:hover { 
  width: auto; 
} 
 
 
/*Hide .txt on hover*/ 
 
#fileName:hover::after { 
  display: none; 
}
<div id="fileName" data-filetype=".txt"> 
  <p>This is the big name of my file.txt</p> 
</div> 
 
<div id="fileName" data-filetype=".txt"> 
  <p>Short.txt</p> 
</div>

Example 3

Browser Compatibility: IE 11, Edge and Chrome.

The content: ... unholy amount of ... on #fileName p::after gives it width. This, along with display: inline-block, is currently the only method that works on the Edge browser / IE 11 as well as Chrome. The display: inline-block breaks this method on Firefox and the .txt is not covered on short filenames.

#fileName { 
  position: relative; 
  width: 122px; 
} 
 
#fileName::after { 
  content: attr(data-filetype); 
  position: absolute; 
  right: 0; 
  top: 0; 
  padding-right: 10px; /*Fixes Edge Browser*/ 
} 
 
#fileName p { 
  white-space: nowrap; 
  overflow: hidden; 
  padding-right: 22px; 
  text-overflow: ellipsis; 
} 
 
#fileName p::after { 
  content: '.........................................................................................................................';/*Fixes Edge Browser*/ 
  background: #FFF; 
  position: relative; 
  display: inline-block;/*Fixes Edge Browser*/ 
  z-index: 1; 
  color: #FFF; 
} 
 
 
/*Show on hover*/ 
 
#fileName:hover { 
  width: auto 
} 
 
#fileName:hover::after { 
  display: none; 
}
<div id="fileName" data-filetype=".txt"> 
  <p>This is the big name of my file.txt</p> 
</div> 
 
<div id="fileName" data-filetype=".txt"> 
  <p>Short.txt</p> 
</div>

CSS crop string in the middle
See more ...