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

2

11

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?

Annmarieannnora answered 1/9, 2016 at 12:49 Comment(0)
S
13

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>
Steeple answered 1/9, 2016 at 14:4 Comment(1)
make sure that parent of div.parent has display:block; propertyVladimir
D
0

The following uses flex and relies on the known width of the button which seems like the use-case here. The whole contained can have dynamic size, of course. The icon can be any size, too.

.parent {
  width: 400px;
  background-color: yellow;
  display: flex;
  justify-content: space-between;
}

.description {
  width: calc(100% - 50px);
  display: flex;
}

.text {
  display: inline-block;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.icon {
  display: inline-block;
  background-color: tomato;
}

.button {
  width: 50px;
  background-color: blue;
}
<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">ICON</span>
  </div>
  <div class="button">
    Button
  </div>
</div>

<div class="parent">
  <div class="description">
    <span class="text">Lorem sit amet</span>
    <span class="icon">ICON</span>
  </div>
  <div class="button">
    Button
  </div>
</div>
Delgadillo answered 1/9, 2016 at 13:11 Comment(2)
I edited my question to clarify my requirements. There could be more than one buttons, and of different width. This is going to be part of an app header, in which every route has different action buttons. Therefore we can't have static widths declared.Annmarieannnora
@ModestosKaffes So basically everything is completely dynamic? Even the icon? If it's an application anyway, you already use a ton of JS, why not add some dynamic CSS?Haileyhailfellowwellmet

© 2022 - 2024 — McMap. All rights reserved.