Search code examples
cssellipsis

How to truncate long text with ellipsis but always show icon after ellipsis


What I'm trying to accomplish is a title which fills its available parent div width, but if its copy doesn't fit in the div it should truncate with ellipsis. Additionally it should also have an icon after it, which shouldn't disappear on truncation, but always show after the ellipsis.

Another requirement is that the parent div should have one or more buttons, of not-specific width, that stay on the far right, but if the div is resized it should truncate the long title, allowing the icon to show next to the ellipsis as I described before.

Visually, my desired result looks like this: truncation problem

Up until now I've achieved the following:

/* Helper styles not relevant to the example */

/* Simple flag object from @csswizardry */

.flag {
  display: table;
  width: 100%;
}
.flag .flag__section {
  display: table-cell;
  vertical-align: middle;
}

/* Right float text from bootstrap */

.text-right {
  text-align: right !important;
}


/* Colors for better visibility */

.container {
  background-color: #55606d;
  color: #333;
  padding: 20px;
}
.flag__section--a {
  background-color: #22d398;
}
.flag__section--b {
  background-color: #91c1f8;
}
.fluid-text__icon {
  background-color: #fecb52;
}



/* Styles relevant to the example */

.container {
  max-width: 700px;
}
.fluid-text {
  text-align: left;
}
.fluid-text__inner {
  max-width: 100%;
}
.fluid-text__inner,
.fluid-text__copy {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.fluid-text__copy,
.fluid-text__icon {
  float: left;
}
.fluid-text__copy {
  padding-right: 5px;
}
.fluid-text__icon {
  margin-top: 30px;
}

/* I'd like to not set explicit max width here */
.title {
  max-width: 600px;
}
<div class='container'>
  <div class='flag'>
    <div class='flag__section flag__section--a fluid-text'>
      <div class='fluid-text__inner'>
        <h1 class='fluid-text__copy title'>
          Lorem ipsum dolor sit amet, consectetur adipisicing elit. Doloremque earum in, voluptas dolorum sit ab modi facere tempora est, sequi molestiae! Commodi vitae sapiente ipsum, nisi facilis impedit aut? Repellendus!
        </h1>
        <span class='fluid-text__icon'>icon</span>
      </div>
    </div>
    <div class='flag__section flag__section--b text-right'>
      <button>ACTION</button>
    </div>
  </div>
</div>

However, my only concern is that I have to explicitly set .title max-width which is not scalable and I would like to avoid it.

Is there any way to do it without js?


Solution

  • Flexbox can solve this, we just have to expend the ellipsis to the .description div and make a few minor tweaks.

    * {
      box-sizing: border-box;
    }
    .parent {
      width: 80%;
      margin: auto;
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 1em;
      padding: .5em;
      border: 1px solid grey;
    }
    .description {
      display: flex;
      align-items: center;
      white-space: nowrap;
      overflow: hidden;
    }
    .text {
      flex: 1;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }
    .icon {
      flex: 0 0 auto;
      background-color: rebeccapurple;
      color: white;
      padding: .5em;
      margin: 0 .25em;
    }
    .button {
      flex: 0 0 auto;
      background-color: #ccc;
      padding: .5em;
    }
    <div class="parent">
      <div class="description">
        <span class="text">Lorem sit amet, consectetur adipisicing elit doloremque earum in, voluptas dolorum sit ab modi facere tempora est, sequi molestiae! Commodi vitae sapiente ipsum, nisi facilis impedit aut? Repellendus!</span>
        <span class="icon">I</span>
        <span class="icon">I</span>
        <span class="icon">I</span>
        <span class="icon">I</span>
      </div>
      <div class="button">
        Button
      </div>
    </div>
    
    <div class="parent">
      <div class="description">
        <span class="text">Lorem sit amet</span>
        <span class="icon">I</span>
        <span class="icon">I</span>
      </div>
      <div class="button">
        Button
      </div>
    </div>