Overflow with ellipsis ruins flex's children sizes - html

I'm displaying response in rows, each of the rows is a flex container with 3 children, split by the flex-basis property. I've added a text to the first child in which I wanted to use an ellipsis in case it's too long. However adding the text completely ruins the view by extending the first flex child (each row has different sizes, the second and third children are not directly underneath each other). It looks like the text length has impact on how much the first child will be extended.
Here's what the code looks like (more or less):
.parent-flex {
display: flex;
justify-content: space-between;
align-content: center;
margin: 0 10px;
.child-1 {
min-width: 0;
display: flex;
flex-direction: column;
flex-basis: 45%;
}
.child-1-text {
display: flex;
flex-wrap: nowrap;
}
.child-2 {
min-width: 0;
flex-basis: 35%;
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
align-content: center;
}
.child-3 {
min-width: 0;
flex-basis: 20%;
display: flex;
flex-wrap: wrap;
justify-content: flex-end;
align-items: flex-end;
flex-direction: column;
}
}
.text-with-ellipsis {
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
<div class="parent-flex">
<div class="child-1">
<div>
Text <span>Additional text</span>
</div>
<div class="text-with-ellipsis">
<span>Text to be shortened with ellipsis.</span>
</div>
<div class="child-1-text">
<span>X</span>
</div>
</div>
<div class="child-2">
<div class="child-2-text"></div>
<div class="child-2-text">
<span>Some more text</span>
</div>
</div>
<div class="child-3">
<div>...</div>
<div>...</div>
</div>
</div>
I was looking through different cases related to flex and overflow but nothing seemed to work for me. I've tried wrapping the div with the ellipsis with another div, adding min-width: 0 to it, flex-shrink and flex-grow but it didn't help (but maybe I was inserting them into wrong places).
When I remove white-space: nowrap from the styles the children ratio is back to normal, but obviously the text isn't wrapped.
I can confirm that the wrapped text div width is dependent on the length of the text inside - the longer it is, the bigger the div gets (ignoring it's parent size). Like the clientWidth (or scrollWidth maybe) is calculated based on the text, not on the desired width.

Do this. I used a table instead of divs but you have to add the classes ".first, .second and .third" on your own. The UI is very similar and the third column auto resizes.
THE CODE SNIPET IS BELOW
table {
--first: 45vw;
/*width of the first column*/
--second: 20vw;
/*width of the second column*/
--third: clac(abs(100vw - var(--first) - var(--second)));
/*third column: auto resize*/
width: 100%;
}
td {
text-align: left;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.first {
width: calc(var(--first) - 16px);
max-width: calc(var(--first) - 16px);
}
.second {
width: calc(var(--second) - 16px);
max-width: calc(var(--second) - 16px);
}
.third {
width: calc(var(--third) - 16px);
max-width: calc(var(--third) - 16px);
}
<table border='1'>
<thead>
<tr>
<th class='first'>Title1</th>
<th class='second'>Title2</th>
<th class='third'>Title3</th>
</tr>
</thead>
<tbody>
<tr>
<td class='first'>Text Additional text</td>
<td class='second'>Some more text</td>
<td class='third'>Dummy text</td>
</tr>
<tr>
<td class='first'>Text to be shortened with ellipsis</td>
<td class='second'>Nice to meet you</td>
<td class='third'>See you soon</td>
</tr>
</tbody>
</table>

You had a couple syntax errors in your CSS which I have fixed below. This fixes the issue with the elements extending beyond the bounds set by flex-basis
.parent-flex {
display: flex;
justify-content: space-between;
align-content: center;
margin: 0 10px;
}
.child-1 {
min-width: 0;
display: flex;
flex-direction: column;
flex-basis: 45%;
}
.child-1-text {
display: flex;
flex-wrap: nowrap;
}
.child-2 {
min-width: 0;
flex-basis: 35%;
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
align-content: center;
}
.child-3 {
min-width: 0;
flex-basis: 20%;
display: flex;
flex-wrap: wrap;
justify-content: flex-end;
align-items: flex-end;
flex-direction: column;
}
.text-with-ellipsis {
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
<div class="parent-flex">
<div class="child-1"></div>
<div>
Text <span>Additional text</span>
</div>
<div class="text-with-ellipsis">
<span>Text to be shortened with ellipsis.</span>
</div>
<div class="child-1-text">
<span>X</span>
</div>
<div class="child-2">
<div class="child-2-text"></div>
<div class="child-2-text">
<span>Some more text</span>
</div>
</div>
<div class="child-3">
<div>...</div>
<div>...</div>
</div>
</div>

You should add width to the .text-with-ellipsis class. I also changed flex-basis with width and max-width.
.parent-flex {
display: flex;
justify-content: space-between;
align-content: center;
margin: 0 10px;
.child-1 {
min-width: 0;
display: flex;
flex-direction: column;
width: 45%;
max-width: 45%;
}
.child-1-text {
display: flex;
flex-wrap: nowrap;
}
.child-2 {
min-width: 0;
width: 35%;
max-width: 35%;
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
align-content: center;
}
.child-3 {
min-width: 0;
width: 20%;
max-width: 20%;
display: flex;
flex-wrap: wrap;
justify-content: flex-end;
align-items: flex-end;
flex-direction: column;
}
}
.child-1 .text-with-ellipsis {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
width: 70%;
}
<div class="parent-flex">
<div class="child-1">
<div>
Text <span>Additional text</span>
</div>
<div class="text-with-ellipsis">
<span>Text to be shortened with ellipsis.</span>
</div>
<div class="child-1-text">
<span>X</span>
</div>
</div>
<div class="child-2">
<div class="child-2-text"></div>
<div class="child-2-text">
<span>Some more text</span>
</div>
</div>
<div class="child-3">
<div>...</div>
<div>...</div>
</div>
</div>

The only solution I have right now is setting the width of the .text-with-ellipsis to a defined size. I used media queries to help it scale up and down for different screen sizes. So something like this:
.text-with-ellipsis {
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
width: 500px;
#media (max-width: 1400px) {
width: 400px;
}
}

Related

css text-overflow: ellipsis does not work properly on span

I have a span in a div like this:
As you can see, the text gets overflowed, but not with the three dots, as usual, when you use text-overflow: ellipsis.
This is my relevant html:
<div class="row main">
<span class="kurzbezeichnung">
<mat-icon svgIcon="file"></mat-icon>
Hello! This is a longer text to see if overflow ellipsis effect will get
applied!
</span>
//here is some more stuff of course, but this is the relevant code
</div>
This is the relevant CSS:
.row {
& span {
display: flex;
align-items: center;
gap: 6px;
white-space: nowrap;
}
}
.kurzbezeichnung {
width: 150px;
max-width: 150px;
overflow: hidden;
text-overflow: ellipsis;
}
.row {
display: flex;
flex-direction: row;
gap: 18px;
width: 100%;
}
Why does it overflow without the three dots?
Change the span tag to div and add a 'white-space:nowrap' to the class
HTML
<div class="row main">
<div class="kurzbezeichnung">
<mat-icon svgIcon="file"></mat-icon>
Hello! This is a longer text to see if overflow ellipsis effect will get
applied!
</div>
//here is some more stuff of course, but this is the relevant code
</div>
CSS
.row {
& span {
display: flex;
align-items: center;
gap: 6px;
white-space: nowrap;
}
}
.kurzbezeichnung {
width: 150px;
max-width: 150px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.row {
display: flex;
flex-direction: row;
gap: 18px;
width: 100%;
}

Vertical scrolling for multiple div tags inside a div tag

I am trying to create a scrollable file tree. Minimal code can be found below.
https://jsfiddle.net/3kLmchot/1/
Problem is when I try to add overflow-y: scroll;, to the filebrowse-outer div, the first few items are not visible at all. This problem gets worse when I add more divs.
It seems like items are added about the center of the filebrowse-outer div, so the items that are added at the bottom can be found via scrolling, but the items that are added at the top are invisible. (see the visual aid below)
item 1
item 2
center of the div
item 3
item 4
Scroll bar forms at around item 2, which makes item 1 invisible. Does anyone know why this is happening, and potential solutions?
I got it to work with the following styles, specifically removing justify-content: center; from your .flex-container that is being used by multiple divs and only applying it to the one that is for .flex-container.filebrowse-inner
.side-bar {
position: fixed;
width: 20%;
height: 200px;
display: flex;
flex-direction: column;
}
.flex-container {
display: flex;
/* justify-content: center; <-- THIS LINE IS CAUSING THE ISSUE */
align-items: center;
}
.flex-container.filebrowse-outer {
flex-direction: column;
border: 1px solid #f00;
overflow-y: scroll;
align-items: stretch;
}
.flex-container.filebrowse-inner {
flex-direction: row;
justify-content: center;
width: 100%;
padding-bottom: 15px;
text-align: left;
position: relative;
}
/* .display-container {
width: 70%;
overflow: auto;
} */
I think that you meant to have scroll bar in the external div with class 'side-bar', if yes:
.side-bar {
position: fixed;
width: 20%;
height: 200px;
display: flex;
flex-direction: column;
overflow-y:scroll;
}
.flex-container {
display: flex;
justify-content: center;
align-items: center;
}
.flex-container.filebrowse-outer {
flex-direction: column;
border: solid;
min-height: max-content; /* For safari*/
/* overflow-y: scroll; */
align-items: stretch;
}
.flex-container.filebrowse-inner {
flex-direction: row;
width: 100%;
min-height: max-content; /* For safari*/
padding-bottom: 15px;
text-align: left;
position: relative;
}
.display-container {
width: 70%;
overflow: auto;
}
<div class="side-bar">
<div class="flex-container filebrowse-outer">
<div class="flex-container filebrowse-inner">
<div class="display">
<p>Click Me 1!</p>
</div>
</div>
<div class="flex-container filebrowse-inner">
<div class="display">
<p>Click Me 2!</p>
</div>
</div>
<div class="flex-container filebrowse-inner">
<div class="display">
<p>Click Me 3!</p>
</div>
</div>
<div class="flex-container filebrowse-inner">
<div class="display">
<p>Click Me 4!</p>
</div>
</div>
</div>
</div>
You can then move the border to 'side-bar' class.

Nested flex containers with overflow and ellipsis not working

I have trouble getting text-overflow: ellipsis and overflow: hidden working the way I need it.
Basically, I need to get the left div with class item1 and text "Please truncate me" to shrink as the width of the container decreases so that both item1 and item2 are on the same row.
No matter what I try I end up with the row overflowing and it never shrinks.
Tried various solutions from here but didn't manage to get any working the way I need.
.mainwrapper {
display: flex;
justify-content: center;
width: 100%;
max-width: 100%;
height: 100%;
max-height: 100%;
}
.content {
display: flex;
align-items: center;
justify-content: center;
margin-top: 20px;
margin-bottom: 20px;
max-width: 800px;
width: 100%;
height: 400px;
background-color: red;
}
.top-container {
display: flex;
flex-wrap: wrap;
width: 80%;
height: 80%;
background-color: cyan;
}
.title {
background-color: white;
}
.table-container {
display: table;
}
.skills-container {
width: 100%;
display: block;
background-color: green;
}
.skill-row {
width: 100%;
display: flex;
justify-content: start;
background-color: blue;
}
.item1 {
display: flex;
flex-wrap: nowrap;
}
.item2 {
flex-shrink: 0;
display: flex;
flex-wrap: nowrap;
}
.item-content {
display: flex;
}
.item-details {
display: flex;
}
.text1 {
display: inline-block;
white-space: nowrap;
background-color: yellow;
}
.small-button {
display: flex;
height: 50px;
width: 50px;
background-color: green;
}
.overflow-toverflow {
overflow: hidden;
text-overflow: ellipsis;
}
.flex-w {
flex-wrap: wrap;
}
.flex-nw {
flex-wrap: nowrap;
}
.flex-min {
flex: 1 1 auto;
min-width: 0;
}
.flex-sh-0 {
flex-shrink: 0;
}
.min0 {
min-width: 0;
}
<div class="mainwrapper">
<div class="content flex-min">
<div class="top-container flex-min">
<div class="title">Your skills</div>
<div class="table-container">
<div class="skills-container">
<div class="skill-row flex-nw flex-min">
<div class="item1 flex-min">
<div class="item-content">
<div class="small-button"></div>
<div class="text1 overflow-toverflow">Please truncate me! Please truncate me!Please truncate me!Please truncate me!Please truncate me!Please truncate me</div>
</div>
</div>
<div class="item2 flex-sh-0">
<div class="small-button"></div>
<div class="text1">Relevance: None Whatsoever None</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
codepen:
https://codepen.io/Tiartyos/pen/Ljxyqr
An initial setting on flex items is min-width: auto. This means that, by default, an item cannot shrink below the size of its content. This prevents the ellipsis from rendering since the item simply expands to accommodate all content.
Most of your flex items have the necessary min-width: 0 override applied. But not all of them.
Also, flex and table properties don't play well together. Mixing them can break a flex layout, which appears to be happening in your case.
With the following adjustments, your layout seems to work.
.table-container {
/* display: table; */
min-width: 0; /* NEW */
}
.item-content {
display: flex;
min-width: 0; /* NEW */
}
revised codepen
More information:
Why doesn't flex item shrink past content size?
(This post would be a duplicate of this link, if it weren't for the display: table matter.)

Fitting child into parent

I have nested flex elements with a text at the bottom. The top element has fixed width that is smaller than text:
.list-header {
display: flex;
width: 150px;
height: 80px;
background-color: #ececec;
}
.list-component {
display: flex;
flex: 1;
padding-left: 24px;
padding-right: 24px;
}
.header-container {
display: flex;
flex: 1;
}
.header-text {
display: flex;
flex-direction: column;
justify-content: center;
overflow: hidden;
}
span {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
<div class="list-header">
<div class="list-component">
<div class="header-container">
<div class="header-text">
<span>long long long long long long text</span>
</div>
</div>
</div>
</div>
I can fix this by applying overflow: hidden; to all elements:
.list-header {
display: flex;
width: 150px;
height: 80px;
background-color: #ececec;
}
.list-component {
display: flex;
flex: 1;
padding-left: 24px;
padding-right: 24px;
overflow: hidden;
}
.header-container {
display: flex;
flex: 1;
overflow: hidden;
}
.header-text {
display: flex;
flex-direction: column;
justify-content: center;
overflow: hidden;
}
span {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
<div class="list-header">
<div class="list-component">
<div class="header-container">
<div class="header-text">
<span>long long long long long long text</span>
</div>
</div>
</div>
</div>
But I don't really like this solution.
Is there are way to fix it using only flex properties?
An initial setting on flex items is min-width: auto. This means that flex items cannot be shorter than the width of their content.
You have white-space: nowrap on the text element. As a result, all flex item ancestors must expand (in a domino effect) to accommodate the length of the text.
The affected flex items are:
.list-component
.header-container
.header-text
Therefore, in order to prevent the text from overflowing the primary container, you need to override the min-width: auto default. The flexbox spec provides two methods for doing this:
Add min-width: 0 to flex items
Add overflow with any value other than visible to flex items. (This is why you were able to fix the problem by adding overflow: hidden. It's actually a clean and valid solution.)
This behavior is explained in more detail in this post:
Why doesn't flex item shrink past content size?
.list-header {
display: flex;
width: 150px;
height: 80px;
background-color: #ececec;
}
.list-component {
display: flex;
flex: 1;
padding-left: 24px;
padding-right: 24px;
min-width: 0; /* NEW */
}
.header-container {
display: flex;
flex: 1;
min-width: 0; /* NEW */
}
.header-text {
display: flex;
flex-direction: column;
justify-content: center;
min-width: 0; /* NEW */
}
span {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
<div class="list-header">
<div class="list-component">
<div class="header-container">
<div class="header-text">
<span>long long long long long long text</span>
</div>
</div>
</div>
</div>

Make flex-direction switch to column if there's not enough space in a row

In the example below, what I want is to have .inner-flexbox have flex-direction: row; when its child elements can fit on a single row, but switch to flex-direction: column; when they cannot. I don't think media queries are what I want here because I would be basing them on whether the viewport width is greater than or less than the width of all the <div>s in .inner-flexbox in a row plus the width of the <aside>. Basically, I don't want the items inside .inner-flexbox wrapping—I want them either all in one row, or all in one column.
(distilled example): I have a flexbox that contains two items. One is a "normal" element, the other is another flexbox.
.outer-wrapper
{
display:flex;
width: 100%;
height: auto;
background-color: gray;
flex-wrap: nowrap;
}
.inner-flexbox
{
display: flex;
flex-wrap: wrap;
flex-direction: row;
}
.inner-flexbox > div
{
width: 10rem;
height: 10rem;
background-color: salmon;
margin: 10px;
}
aside
{
background-color: blue;
width: 15rem;
height: 15rem;
}
<div class="outer-wrapper">
<div class="inner-flexbox">
<div>Block 1</div>
<div>Block 2</div>
<div>Block 3</div>
</div>
<aside><!-- Other content here --></aside>
</div>
Try This Code
.outer-wrapper {
display: flex;
width: 100%;
height: auto;
background-color: gray;
flex-wrap: nowrap;
}
.inner-flexbox {
width: 75%;
display: flex;
flex-wrap: wrap;
flex-direction: row;
flex-flow: row wrap;
justify-content: space-between;
}
.inner-flexbox>div {
width: 10rem;
height: 10rem;
background-color: salmon;
margin: 10px;
}
aside {
width: 25%;
background-color: blue;
width: 15rem;
height: 15rem;
float: right;
display: block;
}
<div class="outer-wrapper">
<div class="inner-flexbox">
<div>Block 1</div>
<div>Block 2</div>
<div>Block 3</div>
</div>
<aside>
<!-- Other content here -->
</aside>
</div>
In the end I resorted to scripting, as #LGSon suggested. I used jQuery to compare the total width of the inner flexbox to the width of the container minus the width of the item next to it.