How to Use CSS to Crop a String from the Middle

My file has a long name and I am using CSS text-overflow: ellipsis to crop it.

<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>

Currently, the output looks like this:

This is the bi...

However, I would like to keep the file extension visible, creating an output similar to this:

This is the... le.txt

Is it achievable only with CSS?

As all my files are txt, I attempted to use text-overflow: string, but it seems to only function in Firefox:

 text-overflow: '*.txt';

Answer №1

Check out this creative CSS solution that utilizes the data-* attribute and two ::after pseudo-elements. I've also included an optional hover effect and a way to show all text (the #fileName::after pseudo-element must be removed when displaying full text).

Sample 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>


Exploring Advanced Techniques — concealing the appended filetype for short filenames

The #fileName p::after has a background color that blends with the text's background, effectively covering the ".txt" for brief filenames that don't get cut off by overflow: hidden.

Note the use of padding-right: 22px which positions the ".txt" beyond the ellipsis.

For different approaches with varying browser compatibilities, refer to examples 2 and 3 below. It's challenging to hide the ".txt" uniformly across all browsers.

Sample 2

Test Results on Chrome and Firefox: Compatible.

The #fileName p::after uses a matching background color technique to obscure the ".txt" when dealing with truncated filenames due to overflow: hidden.

Note the application of padding-right in each ::after pseudo-element. padding-right: 22px extends the cover past the ellipsis, while padding-right: 100% assigns the pseudo-element its width. Unfortunately, Edge and IE 11 do not respond to padding-right: 100%.

#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>

Sample 3

Browser Compatibility Check: Supportive on IE 11, Edge, and Chrome.

The expansive content: ... complex string ... on #fileName p::after defines its width. This, combined with display: inline-block, is presently the sole method effective on Edge / IE 11 as well as Chrome. However, display: inline-block disables this mechanism on Firefox, leaving the ".txt" exposed for short filenames.

#fileName {
  position: relative;
  width: 122px;
}

#fileName::after {
  content: attr(data-filetype);
  position: absolute;
  right: 0;
  top: 0;
  padding-right: 10px; /*Resolves Edge Browser Issue*/
}

#fileName p {
  white-space: nowrap;
  overflow: hidden;
  padding-right: 22px;
  text-overflow: ellipsis;
}

#fileName p::after {
  content: '.........................................................................................................................';/*Resolves Edge Browser Issue*/
  background: #FFF;
  position: relative;
  display: inline-block;/*Resolves Edge Browser Issue*/
  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>

Answer №2

After some thought, this is the solution I have come up with... It may be beneficial to tidy up the front portion of the second span...

CSS

#fileTitle span {
      white-space: nowrap;
      overflow: hidden;
      display:inline-block;
 }
#fileTitle span:first-child {
      width: 100px;
      text-overflow: ellipsis;
 }
#fileTitle span + span {
      width: 30px;
      direction:rtl;
      text-align:right;
 }

HTML

<div id="fileTitle">
    <span>Here is the title of my document.docx</span>
    <span>Here is the title of my document.docx</span>
</div>

http://jsfiddle.net/c8everqm/1/

Answer №3

Here's a helpful tip that I found effective:

<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;"> Here comes a very long sentence that is cut short for readability</div>
   <div style="flex: 1 0 content;white-space:nowrap;"> &nbsp;but remains flexible in layout</div>
</div>

Answer №4

Presented here is a dynamic solution utilizing flexbox, which adjusts according to the user resizing the browser window. One drawback is that the text following the ellipsis maintains a fixed size, preventing placement of the ellipsis at the exact center 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>

To observe the effect, adjust the size of the right-hand side boxes on jsfiddle:

https://jsfiddle.net/L9sy4dwa/1/

If you're open to using direction: rtl creatively, it's possible to position the ellipsis precisely in the middle of the text by tweaking 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 view an animated gif demonstrating this on https://i.sstatic.net/CgW24.gif.

Here's a jsfiddle showcasing this approach:

https://jsfiddle.net/b8seyre3/

Answer №5

After experimenting with various CSS solutions, I discovered a common issue – when the text is short, it would display as "short text short text" instead of just "short text". To address this, I decided to combine CSS with JavaScript.

In my JavaScript code (based on Jeremy Friesen's with some modifications), I created a function called shrinkString:

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;
}

To implement this in HTML, I used the following code snippet:

<div>
  <h5>{shrinkString("can be very long of short text", 50, 15)}&nbsp;</h5>
</div>

For styling, I applied the necessary CSS properties to achieve the desired effect:

div {
  width: 200px;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

I trust that this solution will prove helpful. Apologies for any formatting errors as this marks my debut answer on SO.

Answer №6

Here is a handy JavaScript function:

var cropWithExtension = function(inputString, maxLength, trailingCharCount) {
    var croppedString = inputString;

    if(inputString.length > maxLength){
        var start = inputString.substr(0, inputString.length - (maxLength - trailingCharCount - 3));
        var middle = "...";
        var end = inputString.substr(-trailingCharCount);

        croppedString = start + middle + end;
    }

    return croppedString;
}

var shortString = cropWithExtension("This is the big file.txt", 21, 6);

Answer №7

Input ---A gigantic text file named file.txt

To shorten the file name, you can use the following JavaScript code snippet:

Output ---A gigantic...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:

**Send the $scope.referenceFileName in the JSON object to the back end

$scope.fileName this will be used in the front-end

Answer №8

The approved solution is effective. One suggestion for enhancing Browser Compatibility would be to implement detection for truncation. Consider making the entire CSS conditional based on this.

const wrap = document.getElementById('filenameText');
  if (wrap.offsetWidth >= wrap.scrollWidth) {
    this.truncation = false;
  }

 <div
    :data-filetype="data-filetype"
    :class="[truncation && 'truncateFilenamClass']"
  >

Answer №9

After encountering issues with buggy and hard-to-maintain CSS solutions that required adding attributes or elements to separate text, I decided to create a straightforward JavaScript solution. By simply providing your text and the maximum length allowed, you can easily truncate the text in the middle.

const truncateMiddle = (text, maxCharacters) => {
  const txtLength = text.length;
  const txtLengthHalf = maxCharacters ? Math.round(maxCharacters / 2) : Math.round(txtLength / 2);
  return text.substring(0, (txtLengthHalf -1)).trim() + '...' + text.substring((txtLength - txtLengthHalf) + 2, txtLength).trim();
}

truncateMiddle('Once upon a time there was a little bunny', 10);

Returns: Once...nny

The only downside is that it may require additional functionality to be fully responsive.

Answer №10

Although CSS is effective, I believe using JavaScript can lead to more precise outcomes. Why? Because with JS, you have the ability to manipulate the number of initial and final text elements. You only need 2 lines of JavaScript code to trim a string based on your specifications:-

    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>

In addition, with JS, you can select the first n words instead of just the initial characters according to your preferences. Here is the JavaScript code for this functionality:

    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>

Answer №11

When looking for a solution that is compatible with liquid layouts, I devised a method utilizing flexbox. One downside is the requirement of three elements, but the clear advantage is that everything will be displayed if there is enough space. Depending on the situation, an extra white-space rule may be necessary for the paragraph, along with a minimum width for the first span.

<p><span>This is where you insert long text, up until the</span><span>very end</span></p>

p {display:flex}
p span:first-child {flex-shrink:1; text-overflow: ellipsis; overflow: hidden}

UPDATE: Technically, the flex-shrink property is not required because it is already the default behavior for flex-items. However, this is not the case in IE10. In this instance, prefixing is essential.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

An issue occurred during the building of the module (from ./node_modules/sass-loader/dist/cjs.js) and resulted in

Within the app directory, I've created a new folder called styles > custom > loader.scss. In the styles.scss file, I included the following import: @import "styles/custom/loader.scss"; However, upon doing so, an error message appeared ...

What is the correct way to incorporate scrollIntoView() using jQuery?

I'm trying to implement a jQuery function that will enable the last reply to scroll into view. This is my current code: function displayLastReply(replies){ replies.each(function() { if($(this).index() < nIniRep || afterReply){ $( ...

SweetAlert html is not recognizing ng-app, but it functions correctly within the html body

When inserting a bootstrap table inside a SweetAlert, I encountered an issue where using ng-app or ng-repeat to populate data inside the table's rows did not call ng-app. However, when populating the table outside of the SweetAlert in the body, ng-app ...

Changing the background color to white causes the progress bar line to become indiscernible

Here's how my form appears: Once I set the container to be: <div class="container" style="background:white;"> I want to make it white and ensure that the progress bar is visible. Any suggestions on how to achieve this? CSS: ...

``Change the color of the sections in a 3D pie chart on a Highcharts

I am looking to create a custom pie chart with two different colors: one for the main surface and another for the sides. Currently, I can only configure the lighter blue color for the main surface, but I would like to also change the darker blue color for ...

Generate a unique identifier for the HTML content

Is there a more efficient way to assign unique id tags to certain words using vanilla javascript? For example: <p>All the king's horses ran away.</p> For instance, "All" would have the id "term1", "King's" would have "term2", and ...

What is the key to ensuring the content in your canvas adapts to different screen sizes

Greetings! I wanted to extract the values from this specific meta tag: <meta name="viewport" property="viewport" content="width-device-width, initial-scale=1"> To retrieve content from a meta tag using JavaScript, I used the following code snippet: ...

How to utilize the ternary operator efficiently to evaluate multiple conditions in React

Is there a way to change the style based on the route using react router? I want the description route to display in orange when the user is in the description route, white when in the teacher-add-course route, and green for all other routes. However, th ...

Reactively responsive table view

I am new to CSS and recently discovered a responsive table on this website that I would like to incorporate into my application. My challenge is figuring out how to switch the table layout from left to right (headers on the right and values on the left) w ...

What is the best way to horizontally align my divs and ensure they stack properly using media queries?

My layout is not working as expected - I want these two elements to be side by side in the center before a media query, and then stack on top of each other when it hits. But for some reason, it's not behaving the way I intended. I've tried to ce ...

Setting the height of a div tag in CSS/HTML5 to match the current height of the browser window

Is there a way to make the height of my div tag always equal to the height of the browser's window, so it adjusts automatically when the browser is resized? I have tried using .class { height: 100%; } But this doesn't work. I've learne ...

Convert a div into a clickable link using JavaScript without using too many classes or any ids

After using shortcodes generated by functions.php in a WordPress parent theme, I have come across the following HTML code: <div class="pricing-table-one left full-width "> <div class="pricing-table-one-border left"> <div class=" ...

The dimensions on Next.js pages exceed those of the viewport by a significant margin

I have recently encountered a perplexing issue where the dimensions of my webpage appear to be 2.7 times larger than the viewport, even when there is no content or styles applied. The strange part is that it seems as though the page has been scaled up, eve ...

Having trouble positioning the button on the right side of the page and aligning the text in the center of the page

Having trouble positioning the button to the right of the page and aligning the text in the center, despite adding CSS properties such as float: right. <div id="project-heading" style = "margin-top: 0px; padding-bottom: 0px;margin-bottom: 0px ; padd ...

delete the initial background color assigned to the button

The "ADD TO CART" and "save design" buttons are currently displaying as shown in the image below. I would like to make the "SAVE DESIGN" button look similar to the "ADD TO CART" button, meaning I want to remove the background-color and dot symbol. Code ...

Creating Functional Tabs Using CSS and JavaScript

I've been experimenting with this code snippet, trying to get it to work better. It's still a work in progress as I'm new to this and have only customized it for my phone so far. The issue can be seen by clicking on the Projects and Today ta ...

What is the process of uploading a video and showcasing it on an HTML page?

I have successfully uploaded images and displayed them on an HTML page. Now, I am looking to do the same for videos. Here is my current code: $('#addPhotosBtn').click(function() { $(this).parents().find('#addPhotosInput').click(); }) ...

Issue with CSS background color not extending to full screen in webkit browsers when using 960.gs grid system

When using 960.gs, I have created a login screen with a div for the login form that has a background image. This div is positioned below a header, which centers it in the browser window. In my CSS, I am setting the body color as follows: body { backgr ...

Using jQuery to compare input with the current select optgroup choices

I'm struggling with looping through options within a form select. The options are grouped into optgroups, and I believe this is where my issue lies as I can't seem to find the correct syntax. My objective is to compare the value entered using .v ...

Steps to insert a logo into a Bootstrap navbar

Hey there, I'm having trouble fitting my logo into a Bootstrap navbar. The issue is that the logo appears larger than the navbar itself, and I've tried various solutions without success. Can someone please assist me with this problem? Below is th ...