Fitting child into parent - html

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>

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

In container with flex-grow: 1 the content is overflowing when it should be scrollable

I have a container that is flex-grow sized to fill up the remaining space within a fixed size container.
Within the flex-grow container, I have another div that is a lot bigger than the flex sized container. How do I make it so that the content-wrapper element is scrollable instead of the child element overflowing.
Thank you!
.main-content-container {
padding: 0 20px;
display: flex;
flex-flow: column nowrap;
grid-gap: 10px;
height: 550px;
background: green;
}
.sub-content-container {
width: 300px;
background: grey;
flex-grow: 1;
display: flex;
flex-flow: column nowrap;
}
.content-wrapper {
flex-grow: 1;
display: flex;
flex-flow: column nowrap;
overflow: auto;
}
.content-container {
height: 10000px;
background: #555;
}
body {
background: black;
color: white;
padding-bottom: 30px;
}
<div class='main-content-container'>
<p>stuff</p>
<div class='sub-content-container'>
<p>header</p>
<div class='content-wrapper'>
<div class="content-container">I WANT THIS TO STAY WITHIN THE CONTENT-WRAPPER</div>
</div>
</div>
</div>
Generally speaking, for the overflow property to work, the container needs to be overflowed. That requires a fixed length on the container. Without a fixed length (height or width), there's nothing to trigger an overflow. The flex-grow property doesn't establish a fixed length, so it doesn't work.
Of course, setting a fixed height on your container is not an option if you want a dynamic layout.
So, to solve both problems, set the container to height: 1px.
this establishes the fixed length;
it doesn't interfere with the dynamic lengths; and,
the flex-grow property expands the container to full height
But there's one more problem. The nested flex container in column direction seems to be ignoring the overflow property. This is possibly because of the nesting in a flex formatting context. Hence, if possible, switch that container back to a block formatting context.
Make these adjustments to your code:
.content-wrapper {
height: 1px; /* new */
flex-grow: 1;
/* display: flex; */
flex-flow: column nowrap;
overflow: auto;
}
.main-content-container {
padding: 0 20px;
display: flex;
flex-flow: column nowrap;
grid-gap: 10px;
height: 550px;
background: green;
}
.sub-content-container {
width: 300px;
background: grey;
flex-grow: 1;
display: flex;
flex-flow: column nowrap;
}
.content-wrapper {
height: 1px; /* new */
flex-grow: 1;
/* display: flex; */
flex-flow: column nowrap;
overflow: auto;
}
.content-container {
height: 10000px;
background: #555;
}
body {
background: black;
color: white;
padding-bottom: 30px;
}
<div class='main-content-container'>
<p>stuff</p>
<div class='sub-content-container'>
<p>header</p>
<div class='content-wrapper'>
<div class="content-container">I WANT THIS TO STAY WITHIN THE CONTENT-WRAPPER</div>
</div>
</div>
</div>
jsFiddle demo

Responsive flex row display until min width reach

Basically, in a container, I have tabs (with ul.li) and another div (search box) next to these tabs which are displayed in a row using flex.
I want it responsive following this workflow:
if the width increases, the search section increases to fit the available space. I manage to do using the property flex-basis: 100%
if the width decreases, the search section decreases as well with the property flex-basis: 100%. However, I would like the search section to decrease until 100px and then tabs will decrease displaying ellipsis. I tried using flex-shrink or flex-grow without success since I am not an expert with flexbox.
I reproduced the simplest example in order to illustrate what I am saying.
body {
padding: 50px;
font-family: sans-serif;
}
.container {
resize: horizontal;
overflow: auto;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
border: 1px solid black;
}
.tabs__list {
align-items: flex-start;
display: flex;
list-style: none;
margin: 0;
padding: 0;
border-bottom: 0;
margin-right: 28px;
width: unset;
}
button {
height: 34px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.search {
flex-basis: 100%;
height: 34px;
align-self: end;
min-width: 100px;
background-color: blue;
}
<div class="container">
<ul class="tabs__list">
<li>
<button type="button">Tab Item Number One</button>
</li>
<li>
<button type="button">Tab Item Number Two</button>
</li>
</ul>
<div class="search"></div>
</div>
You need to make use of the power of flex-grow, flex-shrink and flex-basis properties on the children of your flex container.
This is very handy youtube tutorial from Kevin Powell explaining these properties and other important flex-box concepts.
Anyway, here's a solution to your problem with comments explaining what has been added and why.
body {
padding: 50px;
font-family: sans-serif;
}
.container {
resize: horizontal;
display: flex;
overflow: auto;
align-items: center;
flex-wrap: nowrap;
/* don't allow items to go to a new line on shrink */
border: 1px solid black;
min-width: 138px;
/* 100px for the div.search width + 10px inline padding for div.search + 28px margin-rigt from ul.tabs__list */
}
.tabs__list {
flex-grow: 0;
/* this forbids ul from growing, so only div.search can take the remaining space */
flex-shrink: 1;
/* this allows ul to shrink */
flex-basis: content;
list-style: none;
margin: 0;
padding: 0;
border-bottom: 0;
margin-right: 28px;
overflow: hidden;
/* styling the ul with nowrap so that the li's do not go on the next line on shrink */
display: flex;
flex-wrap: nowrap;
}
.search {
flex-grow: 1;
/* this allows div.search to grow and take up the remaining space */
flex-shrink: 0;
/* this forbids div.search to shrink below 100px */
flex-basis: 100px;
/* this works quite like min-width: 100px; but not exactly the same */
align-self: end;
height: 45px;
background-color: blue;
/* more suggested styling to div.search */
color: white;
display: flex;
align-items: center;
padding: 5px;
}
.tabs__list li {
/* display: inline; */
margin: 5px;
padding: 5px;
flex: auto;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
/* the following styling is applied to give li's the look of a button */
border: black 1px solid;
text-align: center;
background-color: lightgray;
cursor: pointer;
}
.tabs__list li:hover {
background-color: gray;
color: white;
}
<div class="container">
<ul class="tabs__list">
<li> Tab Item Number One</li>
<li>Tab Item Number Two</li>
</ul>
<div class="search">Search</div>
</div>
The most important thing an element needs for ellipsis to work is width. Without a width, the browser won't know when the text is actually being cut from its predefined width. I set a width on your container to 100%. Then set each child element (tabs__list and search) to 50%. I also set the li to 50% so each item would take half of that space. However, I still have flex-basis: 100%; so search fills any remaining space.
With this set, you can now just set width: 100%; to your button, which is the defined width it needs so it knows the text is being cut off and it needs to show ellipsis.
Side note: you can still add your min-width: 100px; to search and it will still show ellipsis, but I removed it because it shows a vertical scrollbar.
body {
padding: 50px;
font-family: sans-serif;
}
.container {
resize: horizontal;
overflow: auto;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
border: 1px solid black;
width: 100%;
}
.tabs__list {
align-items: flex-start;
display: flex;
list-style: none;
margin: 0;
padding: 0;
border-bottom: 0;
margin-right: 28px;
width: 25%;
}
li {
width: 50%;
}
button {
height: 34px;
width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.search {
flex-grow: 1;
flex-basis: 100%;
width: 75%;
min-width: 100px;
height: 34px;
align-self: end;
background-color: blue;
}
<div class="container">
<ul class="tabs__list">
<li>
<button type="button">Tab Item Number One</button>
</li>
<li>
<button type="button">Tab Item Number Two</button>
</li>
</ul>
<div class="search"></div>
</div>

ellipsis does not work (flexbox) [duplicate]

This question already has answers here:
text-overflow ellipsis on flex child not working [duplicate]
(4 answers)
Closed 5 years ago.
I'm trying to put ellipsis for text overflow:
parent:
.grid-row {
display: flex;
}
child:
.grid-cell {
display: flex;
flex-grow: 3;
flex-basis: 0;
align-items: center;
padding: 10px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.grid-cell:first-child {
flex-grow: 1;
justify-content: center;
}
And, well the overflow is hidden, but without any ellipsis.
For text overflow to work you need a set width - set a width to your grid-row.
Also remove the display: flex from the grid-cell - see demo below:
.grid-row {
display: flex;
width: 250px;
}
.grid-cell {
/*display: flex;*/
flex-grow: 3;
flex-basis: 0;
/*align-items: center;*/
padding: 10px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.grid-cell:first-child {
flex-grow: 1;
justify-content: center;
}
<div class="grid-row">
<div class="grid-cell">insert text here</div>
<div class="grid-cell">some text</div>
<div class="grid-cell">some more text here</div>
</div>
.grid-cell {
display: flex;
flex-grow: 3;
flex-basis: 0;
align-items: center;
padding: 10px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
word-wrap:normal;
width: ###px;
}
You should set the width of .grid-cell
Add this to your .grid-cell:
max-width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
Works like a charm.

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