"Utilizing an ellipsis within a span element in a table cell to achieve maximum cell

Update

Note: Primarily targeting Chrome (and maybe Firefox) for an extension. However, open to suggestions for a universal solution.

Additional Information

Note: Discovered that lack of spaces in text for A causing overflow issues with B. Situation seems more complex than anticipated. Updated code now allows user input. Test sample without spaces.


I have a fixed positioned box with full width and fixed height placed within a dynamic environment.

+-----------------------------+
|                             |
|                             |
[=============================] << The box.
|                             |
|                             |
...
      <-  dynamic width  ->

The box consists of two key elements A and B. B takes priority in width and is responsible for accommodating its content within the given height, avoiding greedy behavior. A fills the remaining space greedily. When there is text overflow in A, ellipsis should be added, which is where I'm encountering challenges.

Here are some examples:

1. B occupies designated space, A expands to fill width.
+-------------------+--------+
| A________         | __B___ |
+-------------------+--------+

2. A overflows with ellipsis.
+-------------------+--------+
| A_____________... | __B___ |
+-------------------+--------+

3. B grows, A shrinks.
+----------------+-----------+
| A__________... | __B______ |
+----------------+-----------+

After experimenting with various techniques like floats, absolute positioning, and others, I arrived at utilizing a table layout in CSS as my chosen approach. Other methods didn't produce the desired effect. If anyone has alternative solutions, please feel free to share.

The main challenge lies in implementing ellipsis when A overflows.

Is there a way to modify how A is structured to achieve this?

Sample code:

Please disregard the JavaScript, it serves as a tool for displaying overflow visually. (Convenient feature while editing in Firefox's Style Editor)

/* Code may seem messy with unconventional variable usage. */
function Hack() {
    var x     = 0,
        n     = 150,
        wrap  = document.querySelector('#wrap'),
        left  = document.querySelector('#left'),
        right = document.querySelector('#right'),
        txt   = document.querySelector('#txt'),
        ent   = document.querySelectorAll('.entry'),
        log   = document.querySelector('#log'),
        run   = document.querySelector('#run'),
        rt    = document.querySelector('#rt'),
        samp  = document.querySelector('#sample'),
        t     = samp.value
    ;
    this.rt = parseInt(rt.value) || 1000;
    function getComp(e) {
        var x = window.getComputedStyle(e, null);
        return ''+
          ~~(parseInt(x.getPropertyValue('height'))) + 'x' +
          ~~(parseInt(x.getPropertyValue('width')))
        ;
    }
    this.status = function () {
        log.textContent = 'Height / Width for:\n' +
            '  wrap  : ' + getComp(wrap) + '\n' +
            '  left  : ' + getComp(left) + '\n' +
            '  right : ' + getComp(right) + '\n' +
            '  sample: ' + getComp(txt) + '\n'
        ;
    }
    /* Switch between long and short text in sample cells. */
    this.flip = function () {
        txt.textContent = x ? t : (new Array(n)).join(t);
        Array.prototype.forEach.call(ent, function (e) {
            e.textContent = x ? 'abc' : 'abcabc';
        });
        x ^= 1;
        this.status();
    }
    /* Toggle auto run. */
    this.update = function () {
        t = samp.value;
        this.rt = parseInt(rt.value);
        if (!this.rt || this.rt < 10)
            rt.value = this.rt = 100;
        clearInterval(this.ttt);
        if (run.checked)
            this.ttt = setInterval(this.flip.bind(this), this.rt);
    }
    document.addEventListener('click', this.flip.bind(this));
    run.addEventListener('click', this.update.bind(this));
    rt.addEventListener('change', this.update.bind(this));
    samp.addEventListener('keyup', this.update.bind(this));
    this.update();
}
window.addEventListener('load', function () {
    var hack = new Hack();
    hack.flip();
});
*       { margin     : 0;    padding : 0;  }
#log    { margin     : 5pt;  border  : 1px solid #ccc; }
#filler { margin-top : 90px; height  : 2000px; background : #efefef; }
label,
input   { cursor     : pointer; }

/* inner elements of cells in right  -- (B)     */
.hdr,
.entry  { padding    : 2px 5px; }
.hdr    { font-weight: bold; }

#wrap { /* the red thing             -- aka (the box) */
    position   : fixed;
    top        : 135px;
    height     : 23px;
    background : #600;
    color      : #999;
    height     : 20px;
    width      : 100%;
    display    : table-row;
}
#left { /* the green thing           -- aka (A) */
    background : #044;
    display    : table-cell;
    width      : 100%;
}
#txt { /* sample text in left                   */  /* Where I want ellipsis */
    display    : block;
    height     : 20px;
    width      : 100%;
    overflow   : hidden;
    text-overflow: ellipsis;
}
#right { /* the purple / blue thing  -- aka (B) */
    background : rgba(0,0,200,.5);
    height     : 20px;
    display    : table-cell;
    width      : 100%;
    white-space: nowrap;
}
<p>Click document to expand text, or auto-run:</p>
<div>
<input type="checkbox" id="run" checked /><label for="run">Change every </label>
<input type="number" id="rt" value="1000" step="100" /> millisecond.
Sample text: <input type="text" value=" sample" id="sample" />
</div>
<pre id="log"></pre>

<!-- The box -->

<div id="wrap">
  <div id="left">
    <span id="txt">sample <!-- ellipsis here --> </span>     
  </div>
  <div id="right">
      <span class="hdr">Foo</span><span class="entry">abcd</span>
      <span class="hdr">Bar</span><span class="entry">abcd</span>
  </div>
</div>

<!-- End of File: The box -->

<div id="filler">dummy filler page height</div>

Answer №1

Is it acceptable to utilize JavaScript?

The utilization of the text-overflow property is limited to table cells with a predefined width. To address this issue, the snippet below sets the max-width of the span element to the appropriate width.

Integrate this code into your flip function and include it in a resize event listener (if the parent div lacks a fixed width).

txt.style["max-width"] = "calc(" + wrap.clientWidth + "px - " + right.clientWidth + "px)";

Additionally, you'll need to append white-space: nowrap to your #txt style.

function CustomCode() {
    var x = 0,
        n = 150,
        t = 'example ',
        wrap = document.querySelector('#wrap'),
        left = document.querySelector('#left'),
        right = document.querySelector('#right'),
        txt = document.querySelector('#txt'),
        ent = document.querySelectorAll('.entry'),
        log = document.querySelector('#log'),
        run = document.querySelector('#run'),
        rt = document.querySelector('#rt');
    this.rt = parseInt(rt.value) || 1000;
    
    function computeStyle(e) {
        var x = window.getComputedStyle(e, null);
        return '' +
            ~~(parseInt(x.getPropertyValue('height'))) + 'x' +
            ~~(parseInt(x.getPropertyValue('width')))
        ;
    }
    
    this.status = function () {
        log.textContent = 'Height / Width for:\n' +
            '  wrap  : ' + computeStyle(wrap) + '\n' +
            '  left  : ' + computeStyle(left) + '\n' +
            '  right : ' + computeStyle(right) + '\n' +
            '  sample: ' + computeStyle(txt) + '\n'
        ;
    }
    
    this.flip = function () {
        txt.textContent = x ? t : (new Array(n)).join(t);
        
        Array.prototype.forEach.call(ent, function (e) {
            e.textContent = x ? '123' : '123123';
        });
        
        txt.style["max-width"] = "calc(" + wrap.clientWidth + "px - " + right.clientWidth + "px)";
        x ^= 1;
        this.status();
    }
    
    this.toggle = function (r) {
        this.rt = parseInt(rt.value);
        if (!this.rt || this.rt < 10)
            rt.value = this.rt = 100;

        clearInterval(this.ttt);

        if (run.checked)
            this.ttt = setInterval(this.flip.bind(this), this.rt);
    }

    document.addEventListener('click', this.flip.bind(this));
    run.addEventListener('click', this.toggle.bind(this));
    rt.addEventListener('change', this.toggle.bind(this, 1));
    this.toggle();
}

window.addEventListener('load', function () {
    var customCode = new CustomCode();
    customCode.flip();
});
*       { margin     : 0;    padding : 0;  }
#log    { margin     : 5pt;  border  : 1px solid #ccc; }
#filler { margin-top : 90px; height  : 2000px; background : #efefef; }
label,
input   { cursor     : pointer; }

/* inner elements of cells in right  -- (B)     */
.hdr,
.entry  { padding    : 2px 5px; }
.hdr    { font-weight: bold; }

#wrap {
    position   : fixed;
    top        : 135px;
    height     : 23px;
    background : #600;
    color      : #999;
    height     : 20px;
    width      : 100%;
    display    : table-row;
}

#left {
    background : #044;
    display    : table-cell;
    width      : 100%;
}

#txt {
    display    : block;
    height     : 20px;
    width      : 100%;
    overflow   : hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

#right {
    background : rgba(0,0,200,.5);
    height     : 20px;
    display    : table-cell;
    width      : 100%;
    white-space: nowrap;
}
<p>Click on the document to expand the text or enable auto-run:</p>
<div>
<input type="checkbox" id="run" checked /><label for="run">Change every </label>
<input type="number" id="rt" value="1000" step="100" /> millisecond.
</div>
<pre id="log"></pre>

<!-- The box -->

<div id="wrap">
  <div id="left">
    <span id="txt">example <!-- ellipsis here --> </span>
  </div>
  <div id="right">
      <span class="hdr">Foo</span><span class="entry">abcd</span>
      <span class="hdr">Bar</span><span class="entry">abcd</span>
  </div>
</div>

<!-- EOF: The box -->

<div id="filler">dummy filler page height</div>

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

What are the steps to customize the format of Vue3 Datepicker extensions?

Is there anyone who can lend a hand? I am currently using the Vue3 Datepicker and I have received a value that looks like this Thu Jun 23 2022 17:14:00 GMT+0700 (Western Indonesia Time) Does anyone know how to transform it into the following format? Thu, ...

Creating a webpage header with Javascript to mimic an existing design

I am in the process of building a website with 5 different pages, but I want the header to remain consistent across all pages. To achieve this, I plan to use an external JavaScript file (.js). The header includes the website name (displayed as an image) an ...

Accessing an object from a webpage using Selenium: A step-by-step guide

Today marks my debut using Selenium IDE, and I must admit that my knowledge of web development is limited. My team is currently working on a website, and as part of my task, I need to write tests for it. The website features several charts showcasing data ...

Execute the function when the element comes into view

Is there a way to create a function that will automatically attach itself to an element when it comes into view? I have multiple elements on my page - element1, element2, and element3. Instead of using a large if statement, I would like to write a functio ...

Arranging items in a flex container

My goal is to achieve the following layout with flexbox: #box { display: flex; flex-wrap: wrap; flex-direction: row; justify-content: center; justify-items: center; align-items: center; } #spotLight img { width: 15%; height: 15%; } # ...

Lowest value malfunctioning

I have encountered an issue with setting minimum values for 4 things. All 4 things are supposed to have the same minimum value as the first thing, but when moving the slider, everything goes back to normal and works fine. Where could the problem be origina ...

Scroll vertically within a Xamarin Android ListView

I have been attempting to implement a vertical scroll for a list view, but I am facing an issue where all the list view items are displayed even if they exceed the phone's screen size. This is the code snippet I have been using: <LinearLayout xm ...

Enhancing the appearance of a JSX component in React

I have a segment of code within my project that calculates a specific percentage and displays it on the dashboard. <text className="netProfit-circle-text" x="50%" y="50%" dy=".2em" textAnchor="middl ...

Styling CSS for Centering a Heading on an Image's Center

Struggling to center an h3 heading in the middle of an image within a grid? Look no further, as I have 3 images across one row - four columns per image/heading. Check out the desired layout https://i.stack.imgur.com/8VFRt.png I've managed to center t ...

Refresh a specific div element utilizing jQuery

I am facing a challenge with my data table in my Spring MVC project. I want to be able to update or remove data from the table without having to reload the entire page. Below is an example of the HTML div element: <div id="datatable"> </div> ...

The issue of overflowing scroll functionality appears to be malfunctioning

.main-content{ height: 100%; width: 60%; min-height: 800px; background-color: white; border-radius: 5px; margin-left: 1%; border: solid 1px black; } .profile-banner{ display: flex; flex-direction: row; justify-content: space-between; ...

Step-by-step guide on embedding a function in HTML using vbscript

I'm working on a dynamic HTML list that I want to enable or disable based on user input. Typically, you can just use the "enabled" or "disabled" attribute at the end of the select element to control the entire list. However, I'm unsure how to ach ...

Include new material in the upper-right corner of each row

Struggling with various styling techniques like pull-right, float, and row-fluid, I have come here to seek help: My goal is simple - I want a Map to be displayed on the right side of a set of rows. Currently, it looks like this: Although close to what I ...

Passing dynamic scope from Angular to a directive is a seamless process

I am working with a directive that retrieves an attribute value from an http call in the following manner: Controller app.controller("HomeController", function($scope){ $http.get("/api/source").then(function(res){ $scope.info = res.data }); }); ...

Is it possible to create a visual representation (such as a jpg file) of a website page?

Looking to generate an image of a web page, like creating a miniature version of the HTML and images. It doesn't need to be exact (no need for Flash/JavaScript rendering). I plan to use this on Linux - preferably with a Java library, but a command li ...

Attempting to modify the background hue of a Bootstrap 5 Button using javascript

I've been experimenting with changing the background color of a bootstrap 5 button using JavaScript. While I've been able to successfully change the text color with JavaScript, altering the button's color has proven to be elusive. Below is ...

There was a problem compiling the template and an error occurred in the mounted hook

I am encountering a slight issue with testing Vuejs and I am unsure how to resolve the error. Error1: "[Vue warn]: Error compiling template: Component template should contain only one root element. If you are using v-if on multiple elements, use v-e ...

Is there a way to specifically remove only the last row from a table?

Recently, I encountered a problem with my JS code that adds and removes table rows based on user interaction. Adding rows functioned perfectly, but the issue arose when attempting to delete rows. Instead of deleting only the last row as intended, all rows ...

In Firefox, the HTML label fails to activate the corresponding input field when the mouse is moved while clicking

If you click on the label in the example below, it will change the state of the input. document.querySelector("label").addEventListener("click", function() { console.log("clicked label"); }); label { -webkit-user-select: none; -moz-user-select: no ...