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.
Related
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.
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/
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.
Ok. As you can see from the title I am searching a way to do this: http://preview.ab-themes.com/?product=revelance . Just look how the first text is following you when scrolling down the at a certain point it stops. How can I do this?
What you see there is done using the technique called Parallax Scrolling.
Refer : Skrollr
You can resolve it nice with jQuery.
See working Fiddle
CSS:
#div1 {
margin-top: 400px;
margin-bottom: 500px;
height: 200px;
width: 100px;
border: 2px solid black;
padding: 30px;
overflow: hidden;
}
#flowingtext {
top: 0;
margin: 0;
position: relative;
}
JavaScript:
window.onscroll = function () {
if (($(window).scrollTop() - $("#div1").offset().top) >= $("#div1").height() - $("#div1").innerHeight() && ($(window).scrollTop() - $("#div1").offset().top) <= $('#div1').height()) {
$('#flowingtext').css('top', $(window).scrollTop() - $("#div1").offset().top + "px");
}
};
HTML:
<div id="div1">
<h1 id="flowingtext">
its flowing
</h1>
</div>
i wonder how it is possible to have multiple spans inside a div, with the last span floating to the bottom right and taking all the remaining width in the "row".
Here is a fiddle: http://jsfiddle.net/gpakL/
The problem is, that the fullWidth span is not always at the bottom. You can resize your browser window to see the fullWidth span moving.
This is how it should look like:
This is how it shold not look like:
HTML:
<div class="container">
<span class="item">sdfdsfsdf</span>
<span class="item">sdfsdfsdfsdf</span>
<span class="item">dsfdsfdsfsd</span>
<span class="item">fsdfsdfsdffsdf</span>
<span class="item">dsgsdf</span>
<span class="item">dfd</span>
<span class="item">fdfdf</span>
<span class="itemFullWidth">FullWidth</span>
</div>
CSS:
.container {
background-color: blue;
width: 50%;
}
.item {
float: left;
background-color: orange;
height: 30px;
line-height: 30px; /* Vertically center */
margin: 5px;
}
.itemFullWidth {
background-color:green;
display: block;
overflow: hidden;
height: 30px;
line-height: 30px; /* Vertically center */
margin: 5px;
min-width: 80px;
}
If you open to use flexbox, it could be easily done (WebKit demo):
.container {
display: flex;
flex-wrap: wrap; /* allow multiple rows */
}
.container > :last-child {
flex: 1; /* absorb remaining space */
}
check this,
Using position: relative; for the container and position: absolute; for the
.itemFullWidth, you can get it to work to some extent. You'll need some js I guess.
You could consider a JavaScript/jQuery assisted solution for this problem. In a more general case, there are jQuery packages like David DeSandro's Masonry or Packery or Isotope: http://desandro.com/
Here is my version of how you could do this using jQuery.
function resetEndItemWidth() {
var wContainer = $(".container").width();
var minWidthEndItem = parseInt($(".itemFullWidth").css("min-width"));
var endItemMargins = $(".itemFullWidth").outerWidth(true)
- $(".itemFullWidth").outerWidth();
var prevItemOffset = $(".itemFullWidth").prev().offset();
var prevItemWidth = $(".itemFullWidth").prev().outerWidth(true);
var freeWidth = wContainer - (prevItemWidth + prevItemOffset.left);
if (freeWidth < minWidthEndItem) {
newWidth = wContainer - endItemMargins;
} else {
newWidth = Math.max(minWidthEndItem,freeWidth);
}
$(".itemFullWidth").width(newWidth);
}
resetEndItemWidth();
$(window).resize(function(){resetEndItemWidth();});
See the demo at: http://jsfiddle.net/audetwebdesign/m6bx8/
How This Works
I look at the floated sibling before the last item (.itemFullWidth) and determine the amount of free space remaining on the line.
If there is enough free space, I reset the width of the full width item to fill the gap,
otherwise, the full width item is on a separate line and I set it to the width of the parent container.
For full width item (.endItemMargins), you need to account for the left-right margins and you need to get the minimum width from the min-width property.
The min-width requirement could be relaxed if you initialize the original with of the full width item.
Other Comments
The flex box solution is much more elegant. However, it is good to have some options.
Simple jQuery solution, however CSS solutions should be preferred over JS solutions.
http://jsfiddle.net/A8mSu/
HTML:
<div class="container clearfix">
<span class="item">sdfdsfsdf</span>
<span class="item">sdfsdfsdfsdf</span>
<span class="item">dsfdsfdsfsd</span>
<span class="item">fsdfsdfsdffsdf</span>
<span class="item">dsgsdf</span>
<span class="item">dfd</span>
<span class="item">fdfdf</span>
<span class="item itemFullWidth">FullWidth</span>
</div>
JS:
function setWidth()
{
$obj = $('.container .itemFullWidth');
$obj.width('auto').width($obj.parent().width() - $obj.position().left);
}
$(window).resize(setWidth);
$(document).ready(setWidth);
CSS:
.container {
background-color: blue;
width: 50%;
}
.item {
float: left;
background-color: orange;
height: 30px;
line-height: 30px; /* Vertically center */
margin: 5px;
}
.itemFullWidth {
background-color: green;
min-width: 80px;
margin-right: 0;
}
.clearfix:after {
content:"";
display: table;
clear: both;
}
try , Please Checkout http://jsfiddle.net/gpakL/14/
function findWidth (){
var ConWidth = $('.container').width();
var leftWidth = $('.container .item:last').offset().left
var lastItemWidth = $('.container .item:last').width();
var fixPos = ConWidth - (leftWidth + lastItemWidth)
$('.container .itemFullWidth').width( fixPos -20 );
};
$(document).ready(function(){
findWidth();
});
$(window).resize(function(){
findWidth();
});