CSS overflow ellipsis only on first element - html

I am trying to do it so for each line the "place" is always shown. However I want the title to be the one which has the ellipsis when the content is too long.
This is what I have so far:
<ul class="results">
<li class="item"> <span class="title">The numbers in the table specify the first browser version that fully supports the property</span><span class="place">Place</span>
</li>
</ul>
.item {
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap
}
http://jsfiddle.net/m6krvapf/5/
The trouble is it is the end of the line which is cut off, which means the "place" is cut off first. Is it possible to kepe the place there always and only put the ellipsis on the content to the left of it?

You can just wrap the part you want to be ellipsised like so:
<li class="item">
<span class="ellipsis"><span class="title">The numbers in the table specify the first browser version that fully supports the property</span></span>
<span class="place">Place</span>
</li>
then use the following styles:
.item {
white-space: nowrap;
}
.ellipsis {
text-overflow: ellipsis;
overflow: hidden;
display:inline-block;
max-width:85%;
}
Example
For smaller screens where Place is longer than 15% of the screen (around 230px), you can use the following media query:
#media all and (max-width: 230px) {
.item {
overflow:auto;
padding-right: 3em;
}
.ellipsis {
max-width:none;
width:100%;
float:left;
}
.place
{
display:inline-block;
width:3em;
float:right;
margin-right:-3em;
}
}
Example

You can turn spans to blocks, use css floating and swap their place as in this Fiddle, css follows:
.item span {
display: block;
}
.title {
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap
}
.place {
float: right;
}
for this html:
<ul class="results">
<li class="item">
<span class="place">Place</span>
<span class="title">The numbers in the table specify the first browser version that fully supports the property</span>
</li>
<li class="item">
<span class="place">Place</span>
<span class="title">The numbers in the table specify the first browser version that fully supports the property</span>
</li>
</ul>
That way 'Place' stays on right side always. Other solution would be to use original html, but to make spans blocks, float them left and set max-width for span.title as in this Example, which uses this CSS:
.item span {
display: block;
float: left;
line-height: 1em;
}
.title {
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
max-width: calc(100% - 50px);
}

Or you can use a JS function to crop you text and then replace the ... for whatever you want.
function shorten(text, maxLength) {
var ret = text;
if (ret.length > maxLength) {
ret = ret.substr(0,maxLength-3) + "...";
}
return ret;
}
See here:
http://html5hub.com/ellipse-my-text/

Related

Can you put the ellipsis in the middle? [duplicate]

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';
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>
This is the best I can come up with... It might be worthwhile trying to clean up the leading edge of the second span...
CSS
#fileName span {
white-space: nowrap;
overflow: hidden;
display:inline-block;
}
#fileName span:first-child {
width: 100px;
text-overflow: ellipsis;
}
#fileName span + span {
width: 30px;
direction:rtl;
text-align:right;
}
HTML
<div id="fileName">
<span>This is the big name of my file.txt</span>
<span>This is the big name of my file.txt</span>
</div>
http://jsfiddle.net/c8everqm/1/
Here is another suggestion that worked well for me:
<div style="width:100%;border:1px solid green;display:inline-flex;flex-wrap:nowrap;">
<div style="flex: 0 1 content;text-overflow: ellipsis;overflow:hidden;white-space:nowrap;"> Her comes very very very very very very very very very very very very very very very very very very very long </div>
<div style="flex: 1 0 content;white-space:nowrap;"> but flexible line</div>
</div>
Here's a solution that uses flexbox, and is dynamic, (e.g. works when the user resizes the browser window). Disadvantage is that the text after the ellipsis has a fixed size, so you can't put the ellipsis in the exact middle of the text.
CSS
.middleEllipsis {
margin: 10px;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: flex-start;
}
.start {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
flex-shrink: 1;
}
.end {
white-space: nowrap;
flex-basis: content;
flex-grow: 0;
flex-shrink: 0;
}
HTML
<div class="middleEllipsis">
<div class="start">This is a really long file name, really long really long really long</div><div class="end">file name.txt</div>
</div>
Resize the right-hand side boxes on jsfiddle to see the effect:
https://jsfiddle.net/L9sy4dwa/1/
If you're willing to abuse direction: rtl, you can even get the ellipsis right in the middle of the text with some small changes to your CSS:
.middleEllipsis {
margin: 10px;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: flex-start;
}
.middleEllipsis > .start {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
flex-shrink: 1;
}
.middleEllipsis > .end {
white-space: nowrap;
flex-basis: content;
flex-grow: 0;
flex-shrink: 1;
align: right;
overflow: hidden;
direction: rtl;
}
You can see an animated gif of what this looks like on https://i.stack.imgur.com/CgW24.gif.
Here's a jsfiddle showing this approach:
https://jsfiddle.net/b8seyre3/
I tried some of those CSS approach but the problem is if the text is short, you will get "short text short text" instead of "short text".
So I went with CSS + JS approach.
JS (I edited Jeremy Friesen's to fix some cases):
const shrinkString = (originStr, maxChars, trailingCharCount) => {
let shrinkedStr = originStr;
const shrinkedLength = maxChars - trailingCharCount - 3;
if (originStr.length > shrinkedLength) {
const front = originStr.substr(0, shrinkedLength);
const mid = '...';
const end = originStr.substr(-trailingCharCount);
shrinkedStr = front + mid + end;
}
return shrinkedStr;
}
HTML:
<div>
<h5>{shrinkString("can be very long of short text", 50, 15)} </h5>
</div>
CSS:
div {
width: 200px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
I hope it helps. Sorry for the format. This is my first answer on SO.
JavaScript option:
var cropWithExtension = function(value, maxChars, trailingCharCount) {
var result = value;
if(value.length > maxChars){
var front = value.substr(0, value.length - (maxChars - trailingCharCount - 3));
var mid = "...";
var end = value.substr(-trailingCharCount);
result = front + mid + end;
}
return result;
}
var trimmedValue = cropWithExtension("This is the big file.txt", 21, 6);
Input ---This is a very very very very very big file.txt
To truncate the above file name use the below javascript
Output ---This is a very...big file.txt
var selectedFileName = getItemSelected();//Input
$scope.referenceFileName =getItemSelected();
var len = selectedFileName.length;
if(len > 30){
selectedFileName = selectedFileName.substr(0,15)+'... '+selectedFileName.substr(len-15,15);
}
$scope.fileName = selectedFileName;
**
Note:
**Pass the $scope.referenceFileName in the json---back end
$scope.fileName this would be---front end
The accept answer is good. Although for Browser Compatibility, you could do the detection for truncate or not. Make the whole CSS conditional.
const wrap = document.getElementById('filenameText');
if (wrap.offsetWidth >= wrap.scrollWidth) {
this.truncation = false;
}
<div
:data-filetype="data-filetype"
:class="[truncation && 'truncateFilenamClass']"
>
I found out the css solutions quite buggy and hard to maintain, since you need to add attributes or elements to separate text.
I built a quite straight forward Javascript that handles it. Send your text and max length of the text and you get the text truncated in the middle back.
const truncateMiddle = (text, maxCharacters) => {
const txtLength = text.length; // Length of the incoming text
const txtLengthHalf = maxCharacters ? Math.round(maxCharacters / 2) : Math.round(txtLength / 2); // set max txtHalfLength
return text.substring(0, (txtLengthHalf -1)).trim() + '...' + text.substring((txtLength - txtLengthHalf) + 2, txtLength).trim() //Return the string
}
truncateMiddle('Once opon a time there was a little bunny', 10);
Returns: Once...nny
Cons? Sure, it need more functionality to be responsive.
CSS is good, but I think you must do it by JavaScript for more accurate results.
Why?
Because, with JS You can control number of first and last texts of words.
This is just 2 lines of JavaScript code to crop string as per you define:-
let fileName=document.getElementById('fileName')
fileName.innerHTML=fileName.innerHTML.substring(1, 10)+'...'+fileName.innerHTML.slice(-2)
<div id="fileName"> This is the big name of my file.txt</div>
also, you can choose first n words, instead of first few letter/characters with JS, as per you want.
whose JS code is this:-
let fileName=document.getElementById('fileName')
let Words=fileName.innerHTML.split(" ")
let i=0;
fileName.innerHTML=''
Words.forEach(e => {
i++
if(i<5)
fileName.innerHTML+=e+' '
});
fileName.innerHTML+='...'
<div id="fileName"> This is the big name of my file.txt</div>
For a solution that works with liquid layouts I came up with something that uses flexbox. Obvious drawback is that three elements are needed. Obvious advantage: If there is enough room everything will be shown. Depending on circumstances an additional white-space rule for the paragraph might be needed as well as some min-width for the first span.
<p><span>Long text goes in here except for the</span><span>very end</span></p>
p {display:flex}
p span:first-child {flex-shrink:1; text-overflow: ellipsis; overflow: hidden}
ADDENDUM: Strictly speaking, the flex-shrink is not even necessary because it is the default behaviour of the flex-items anyway. This is not so in IE10, however. Prefixing is necessary, too in this case.

CSS: Two texts side by side, one fits content, the other shrinks and overflows until min-width then wraps

I have a title and a url one after the other and I want them to be side by side until they fit on the container width. When they can't fit side by side I want the url to shrink and overflow, until it reaches its min-width, then it can wrap.
Within the same container there are other elements that, if possible, I'd like to keep untouched, behaving like inline or flex items.
I tried to achieve this with flexbox, which had to have flex-wrap: wrap in order to make the subsequent elements flow, but the url would either shrink and make the date element come up on the first row (flex-basis: 0) or expand too much until it wrapped to the following line (flex-basis: some%).
I tried to use float and clear, but couldn't get it to work.
Here's what I'm trying to achieve:
desired result
Here's what I'm getting with flexbox:
url not expanding
Here's what I want when the available space is less than the url min-width:
url wrapping to next line
Here's the relevant html code:
<div class="section" data-section="header">
<h5 class="section-title" style="display: none;">Section title</h5>
<div class="field" data-field="title">
<span class="field-label" style="display: none;">Field label</span>
<span class="field-value">
Some variable length, possibly quite long text here
</span>
</div>
<div class="field" data-field="link">
<span class="field-label" style="display: none;">Link</span>
<span class="field-value">
<a href="https://www.example.com/some-path/a-variable-length-and-possibly-quite-long-url-here.html">
https://www.example.com/some-path/a-variable-length-and-possibly-quite-long-url-here.html
</a>
</span>
</div>
<div class="field" data-field="date">
<span class="field-label">Date</span>
<span class="field-value">2018-05-03 00:00:00</span>
</div>
[...]
</div>
And the current CSS:
.section[data-section=header] .field {
display: inline;
}
.section[data-section=header] .field[data-field=title] {
font-weight: 700;
font-size: 1.2em;
line-height: 0.8;
}
.section[data-section=header] .field[data-field=link] {
font-weight: 600;
font-size: 0.7em;
white-space: nowrap;
max-width: 100%;
position: relative;
}
.section[data-section=header] .field[data-field=link] .field-value {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
max-width: calc(100% - .8em);
display: inline-block;
vertical-align: -.1em;
}
.section[data-section=header] .field[data-field=link]::before {
content: "[";
font-size: 1.2em;
}
.section[data-section=header] .field[data-field=link]::after {
content: "]\000A";
white-space: pre;
font-size: 1.2em;
}
.section[data-section=header] .field[data-field=status]::after {
content: "\000A";
white-space: pre;
}
.section[data-section=header] .field[data-field=title]::after {
content: " ";
line-height: 0px;
font-size: 2.8em;
}
Is there any way I can achieve this without resorting to edit the html layout or isolating the title and url into their own container?

Activate Overflow Ellipsis on SPAN, but also Wrap Around / Use Height if possible

I have SPANs (placed inside LI) on which I want to activate the ellipsis (...) if they are overflowing. However, the problem is I also want them to wrap around and use all the available height.
Consider Snippet #1: This is not what I want because Box #1 shouldn't be ellipsified on one line. There is plenty of Height available, so in this case it should wrap around. Box #2 looks OK here.
.spanbox {
width: 136.5px;
text-overflow: ellipsis;
white-space: nowrap; /* TOGGLING THIS */
overflow: hidden;
display: inline-block;
}
.item1 {
border: 1px solid black;
height: 134px;
width: 136.5px;
}
.item2 {
border: 1px solid black;
height: 17px;
width: 136.5px;
}
<li class="item1">
<span class="spanbox">
(50min) Food preparation and serving
</span>
</li>
<li class="item2">
<span class="spanbox">
(5min) Talking with friends
</span>
</li>
Here's Snippet #2: this isn't what I want either, because now there's no Ellipsis at all in Box #2. But now I got the multi-line wrapping in Box #1, so that looks OK. I turned off the white-space: nowrap style.
.spanbox {
width: 136.5px;
text-overflow: ellipsis;
/*white-space: nowrap;*/ /* TURNED OFF NOW */
overflow: hidden;
display: inline-block;
}
.item1 {
border: 1px solid black;
height: 134px;
width: 136.5px;
}
.item2 {
border: 1px solid black;
height: 17px;
width: 136.5px;
}
<li class="item1">
<span class="spanbox">
(50min) Food preparation and serving
</span>
</li>
<li class="item2">
<span class="spanbox">
(5min) Talking with friends
</span>
</li>
The goal is to use all the available Height in Box #1, but activate the ellipsis on Box #2, so a combination of the above two snippets. Is this possible?
Looks like it's not possible via pure CSS, only a "hack way": https://stackoverflow.com/a/23896375/6053654. And if Javascript solution is OK for you, check this post: Cross browsers mult-lines text overflow with ellipsis appended within a width&height fixed div?
This is a bad solution and won't work in all cases (see accepted answer for real solutions), but based on the fact that it's impossible in plain CSS/HTML I'm now iterating over my LI's and adding the styles dynamically, e.g.
$('li').each(function(index, item) {
// Find one Span with text somewhere inside each Event LI
var innerspan = $(item).find('span');
// Truncate if SPAN Height < LI (Container) Height
if ($(this).height() < $(innerspan).height()) {
// Apply the following CSS
// The Ellipsis also requires a Width value and overflow=hidden
var width = $(this).width();
$(innerspan).css( {
'overflow': 'hidden', 'width' : width,
'text-overflow': 'ellipsis', 'white-space': 'nowrap'
} );
}
// Otherwise default styling with multiline, no ellipsis
// (But won't work if need multiline WITH ellipsis!)
}
});

Responsive breadcrumbs with max crumb width

I'm attempting to create a responsive breadcrumb trail where the overall trail width is restricted and each crumb width is also restricted. Additionally, I'd like to allow for the last crumb to take up any additional space. I've managed to put the following together that mostly demonstrates what I'm going for, but the JQuery solution is less than idea:
$(document).ready(function() {
var $crumbs = $(".container .breadcrumb li");
var overallWidth = $(".container").width();
var crumbWidth = (100 / $crumbs.length) + '%';
$crumbs.css('max-width', crumbWidth);
var totalWidth = 0;
$crumbs.each(function(elt) {
var width = $(this).width();
totalWidth += width;
});
var adjustment = overallWidth - totalWidth;
var $lastCrumb = $(".container .breadcrumb li:last");
var lastCrumbWidth = $lastCrumb.width();
lastCrumbWidth = lastCrumbWidth + adjustment;
$lastCrumb.css('max-width', lastCrumbWidth - 25);
});
.container {
border: 1px solid;
width: 70%;
}
.container .breadcrumb {
padding-left: 10px;
margin: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.container .breadcrumb li {
display: inline-block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.container .breadcrumb li:before {
color: blue;
content: ">";
margin-right: 5px;
}
.container .optional,
.container .optional > div {
display: inline-block;
}
.hidden {
display: none !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1>Breadcrumb Truncation with Ellipsis</h1>
<div class="container">
<ul id="bc1" class="breadcrumb">
<li>Home blah blah</li>
<li>about blah blah blah</li>
<li>super cali fragilistic expialidocious</li>
<li>super duper cali fragilistic expialidocious</li>
<li>UBER super duper cali fragilistic expialidocious</li>
</ul>
<div class="optional">
<div class="hidden"><button>click me</button></div>
<div class="hidden"><span>extra info</span></div>
</div>
</div>
I'm sure this can be accomplished in a pure CSS way, but the solution is alluding me and probably beyond me.
Additionally, ideally this solution would also accommodate the hiding and showing of various elements via the "hidden" that are in the "optional" section.
UPDATE:
I've made some progress with the following, but it still isn't ideal since I'm blindly using a fixed max-width:
.truncate {
max-width: 250px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
&:last-child {
max-width: 100%;
}
}
Here's a jsfiddle demonstrating some of the desired functionality.

CSS crop string in the middle

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';
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>
This is the best I can come up with... It might be worthwhile trying to clean up the leading edge of the second span...
CSS
#fileName span {
white-space: nowrap;
overflow: hidden;
display:inline-block;
}
#fileName span:first-child {
width: 100px;
text-overflow: ellipsis;
}
#fileName span + span {
width: 30px;
direction:rtl;
text-align:right;
}
HTML
<div id="fileName">
<span>This is the big name of my file.txt</span>
<span>This is the big name of my file.txt</span>
</div>
http://jsfiddle.net/c8everqm/1/
Here is another suggestion that worked well for me:
<div style="width:100%;border:1px solid green;display:inline-flex;flex-wrap:nowrap;">
<div style="flex: 0 1 content;text-overflow: ellipsis;overflow:hidden;white-space:nowrap;"> Her comes very very very very very very very very very very very very very very very very very very very long </div>
<div style="flex: 1 0 content;white-space:nowrap;"> but flexible line</div>
</div>
Here's a solution that uses flexbox, and is dynamic, (e.g. works when the user resizes the browser window). Disadvantage is that the text after the ellipsis has a fixed size, so you can't put the ellipsis in the exact middle of the text.
CSS
.middleEllipsis {
margin: 10px;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: flex-start;
}
.start {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
flex-shrink: 1;
}
.end {
white-space: nowrap;
flex-basis: content;
flex-grow: 0;
flex-shrink: 0;
}
HTML
<div class="middleEllipsis">
<div class="start">This is a really long file name, really long really long really long</div><div class="end">file name.txt</div>
</div>
Resize the right-hand side boxes on jsfiddle to see the effect:
https://jsfiddle.net/L9sy4dwa/1/
If you're willing to abuse direction: rtl, you can even get the ellipsis right in the middle of the text with some small changes to your CSS:
.middleEllipsis {
margin: 10px;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: flex-start;
}
.middleEllipsis > .start {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
flex-shrink: 1;
}
.middleEllipsis > .end {
white-space: nowrap;
flex-basis: content;
flex-grow: 0;
flex-shrink: 1;
align: right;
overflow: hidden;
direction: rtl;
}
You can see an animated gif of what this looks like on https://i.stack.imgur.com/CgW24.gif.
Here's a jsfiddle showing this approach:
https://jsfiddle.net/b8seyre3/
I tried some of those CSS approach but the problem is if the text is short, you will get "short text short text" instead of "short text".
So I went with CSS + JS approach.
JS (I edited Jeremy Friesen's to fix some cases):
const shrinkString = (originStr, maxChars, trailingCharCount) => {
let shrinkedStr = originStr;
const shrinkedLength = maxChars - trailingCharCount - 3;
if (originStr.length > shrinkedLength) {
const front = originStr.substr(0, shrinkedLength);
const mid = '...';
const end = originStr.substr(-trailingCharCount);
shrinkedStr = front + mid + end;
}
return shrinkedStr;
}
HTML:
<div>
<h5>{shrinkString("can be very long of short text", 50, 15)} </h5>
</div>
CSS:
div {
width: 200px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
I hope it helps. Sorry for the format. This is my first answer on SO.
JavaScript option:
var cropWithExtension = function(value, maxChars, trailingCharCount) {
var result = value;
if(value.length > maxChars){
var front = value.substr(0, value.length - (maxChars - trailingCharCount - 3));
var mid = "...";
var end = value.substr(-trailingCharCount);
result = front + mid + end;
}
return result;
}
var trimmedValue = cropWithExtension("This is the big file.txt", 21, 6);
Input ---This is a very very very very very big file.txt
To truncate the above file name use the below javascript
Output ---This is a very...big file.txt
var selectedFileName = getItemSelected();//Input
$scope.referenceFileName =getItemSelected();
var len = selectedFileName.length;
if(len > 30){
selectedFileName = selectedFileName.substr(0,15)+'... '+selectedFileName.substr(len-15,15);
}
$scope.fileName = selectedFileName;
**
Note:
**Pass the $scope.referenceFileName in the json---back end
$scope.fileName this would be---front end
The accept answer is good. Although for Browser Compatibility, you could do the detection for truncate or not. Make the whole CSS conditional.
const wrap = document.getElementById('filenameText');
if (wrap.offsetWidth >= wrap.scrollWidth) {
this.truncation = false;
}
<div
:data-filetype="data-filetype"
:class="[truncation && 'truncateFilenamClass']"
>
I found out the css solutions quite buggy and hard to maintain, since you need to add attributes or elements to separate text.
I built a quite straight forward Javascript that handles it. Send your text and max length of the text and you get the text truncated in the middle back.
const truncateMiddle = (text, maxCharacters) => {
const txtLength = text.length; // Length of the incoming text
const txtLengthHalf = maxCharacters ? Math.round(maxCharacters / 2) : Math.round(txtLength / 2); // set max txtHalfLength
return text.substring(0, (txtLengthHalf -1)).trim() + '...' + text.substring((txtLength - txtLengthHalf) + 2, txtLength).trim() //Return the string
}
truncateMiddle('Once opon a time there was a little bunny', 10);
Returns: Once...nny
Cons? Sure, it need more functionality to be responsive.
CSS is good, but I think you must do it by JavaScript for more accurate results.
Why?
Because, with JS You can control number of first and last texts of words.
This is just 2 lines of JavaScript code to crop string as per you define:-
let fileName=document.getElementById('fileName')
fileName.innerHTML=fileName.innerHTML.substring(1, 10)+'...'+fileName.innerHTML.slice(-2)
<div id="fileName"> This is the big name of my file.txt</div>
also, you can choose first n words, instead of first few letter/characters with JS, as per you want.
whose JS code is this:-
let fileName=document.getElementById('fileName')
let Words=fileName.innerHTML.split(" ")
let i=0;
fileName.innerHTML=''
Words.forEach(e => {
i++
if(i<5)
fileName.innerHTML+=e+' '
});
fileName.innerHTML+='...'
<div id="fileName"> This is the big name of my file.txt</div>
For a solution that works with liquid layouts I came up with something that uses flexbox. Obvious drawback is that three elements are needed. Obvious advantage: If there is enough room everything will be shown. Depending on circumstances an additional white-space rule for the paragraph might be needed as well as some min-width for the first span.
<p><span>Long text goes in here except for the</span><span>very end</span></p>
p {display:flex}
p span:first-child {flex-shrink:1; text-overflow: ellipsis; overflow: hidden}
ADDENDUM: Strictly speaking, the flex-shrink is not even necessary because it is the default behaviour of the flex-items anyway. This is not so in IE10, however. Prefixing is necessary, too in this case.