Truncate text in flex item - html

I have a header with a left and right side. The left side contains some text which I want to keep on a single line, truncating with ellipsis if needed. However, when I apply white-space: nowrap to it then the whole header goes outside its container. Here's what I mean:
.container {
width: 300px;
height: 400px;
border: 1px solid black;
}
.header {
height: 80px;
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
border: 1px solid red;
}
.header-right,
.header-left {
display: flex;
align-items: center;
justify-content: center;
border: 1px solid blue;
}
.title {
text-overflow: ellipsis;
white-space: nowrap;
}
img {
height: 20px;
width: 20px;
margin: 10px;
}
<div class="container">
<div class="header">
<div class="header-left">
<img src="https://image.flaticon.com/icons/png/128/181/181548.png">
<span class="title">Title: Keep me on a single line</span>
</div>
<div class="header-right">
<img src="https://image.flaticon.com/icons/png/128/181/181548.png">
<img src="https://image.flaticon.com/icons/png/128/181/181548.png">
<img src="https://image.flaticon.com/icons/png/128/181/181548.png">
</div>
</div>
</div>
Does anyone know how to keep the title on a single line but truncate it so the header doesn't go outside the bounds?

You need to disable the default minimun width by adding min-width:0 and disable the shriking for the images and their container by adding flex-shrink:0; and add overflow:hidden
.container {
width: 300px;
height: 400px;
border: 1px solid black;
}
.header {
height: 80px;
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
border: 1px solid red;
}
.header-right,
.header-left {
display: flex;
align-items: center;
justify-content: center;
border: 1px solid blue;
min-width:0; /* Added */
}
.title {
text-overflow: ellipsis;
white-space: nowrap;
overflow:hidden; /* Added */
}
img {
height: 20px;
width: 20px;
margin: 10px;
flex-shrink:0; /* Added */
}
.header-right {
flex-shrink:0; /* Added */
}
<div class="container">
<div class="header">
<div class="header-left">
<img src="https://image.flaticon.com/icons/png/128/181/181548.png">
<span class="title">Title: Keep me on a single line</span>
</div>
<div class="header-right">
<img src="https://image.flaticon.com/icons/png/128/181/181548.png">
<img src="https://image.flaticon.com/icons/png/128/181/181548.png">
<img src="https://image.flaticon.com/icons/png/128/181/181548.png">
</div>
</div>
</div>
Related:
Why don't flex items shrink past content size? (To understand the min-width)
Why is a flex-child limited to parent size? (To understand the flex-shrink)

Related

How can I move the title to the center

I want to move the title to green area. If I carry to the container it puts blue area. If I decrease container height title getting closer to the squares. But I want the boxes in the center and the title little above of them. How can I do it?
#container {
width: 1200;
height: 600px;
margin: auto;
border: 1px solid grey;
display: flex;
align-items: center;
justify-content: center;
}
.box {
height: 250px;
width: 250px;
margin-left: 25px;
margin-right: 25px;
background-color: red;
}
h1 {
text-align: center;
}
<h1>TITLE!!!</h1>
<div id="container">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
my page
It's the display: flex; that's causing the issue. Here's a working model:
#container {
width: 1200;
height: 600px;
margin: auto;
border: 1px solid grey;
}
.box-wrapper {
display: flex;
align-items: center;
justify-content: center;
}
.box {
height: 250px;
width: 250px;
margin-left: 25px;
margin-right: 25px;
background-color: red;
}
h1 {
text-align: center;
}
<div id="container">
<h1>TITLE!!!</h1>
<div class="box-wrapper">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>
I added a extra wrapper to wrap all the elements and added a display flex to it. Also, You can make use of a gap css property in wrapper class to add extra space between them.
.wrapper {
display: flex;
flex-direction: column;
border: 1px solid grey;
width: 1200px;
height: 600px;
}
#container {
margin: auto;
//border: 1px solid grey;
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
}
.box {
height: 250px;
width: 250px;
margin-left: 25px;
margin-right: 25px;
background-color: red;
}
h1 {
text-align: center;
}
<div class="wrapper">
<h1>TITLE!!!</h1>
<div id="container">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>
Also, the other way to solve this would be to use absolute positioning and adding a top padding to allow space for the div header if extra div is really not required.

How to truncate the text between the children of a flexbox child?

I understand how to truncate the text which is wrapped inside a flex child however this particular case seems a bit complicated.
The desired behaviour is that the text between the two blue blocks should get truncated to keep them inside the red border.
.container {
display: flex;
align-items: center;
justify-content: space-between;
border: 1px solid black;
padding: 10px;
width: 300px;
}
.block {
display: inline-block;
width: 50px;
height: 50px;
}
.container .left {
min-width: 0;
white-space: nowrap;
padding: 10px;
border: 1px solid red;
}
.left .label {
display: inline-block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.left .block {
background-color: blue;
}
.container .right {
padding: 10px;
border: 1px solid blue;
}
.right .block {
background-color: red;
}
<div class="container">
<div class="left">
<div class="block">
</div>
<div class="label">
Is this the real life?
</div>
<div class="block">
</div>
</div>
<div class="right">
<div class="block">
</div>
</div>
</div>
Is this what you are looking for? Basically i added flexbox property for left and right div
.container {
display: flex;
align-items: center;
justify-content: space-between;
border: 1px solid black;
padding: 10px;
width: 300px;
}
.block {
display: inline-block;
width: 50px;
height: 50px;
}
.left {
display: flex;
justify-content: space-between;
align-items: flex-end;
min-width: 0;
white-space: nowrap;
padding: 10px;
border: 1px solid red;
}
.label {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.block {
background-color: blue;
}
.right {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px;
border: 1px solid blue;
}
.right .block {
background-color: red;
}
<div class="container">
<div class="left">
<div class="block">
</div>
<div class="label">
Is this the real life?
</div>
<div class="block">
</div>
</div>
<div class="right">
<div class="block">
</div>
</div>
</div>

How to make nested flex child scrollable

I have a list of messages (which is a flex child) in a container with unknown height and want to make them scrollable. But I cannot find a proper combination of flex-grow: 1, min-height: 0 and other flex tricks to make it working - message list is still bigger than its parent.
When I add overflow-y: auto to its parent - it works but this parent besides messages list includes some content which should not scroll.
Here's my example for this case: https://jsfiddle.net/ecbtrn58/2/
<div class="page">
<div class="messages-section">
<div class="header">Your messages</div>
<div class="content">
<img src="https://http.cat/100" width="70" height="50"/>
<div class="messages-list">
<div class="message">Hi.</div>
<div class="message">Hello.</div>
<div class="message">Good morning.</div>
<div class="message">Yo!</div>
</div>
</div>
</div>
</div>
.page {
background-color: #ddd;
width: 300px;
height: 300px;
.messages-section {
display: flex;
flex-direction: column;
width: 50%;
height: 100%;
background-color: #ccc;
.header {
background: #bbb;
padding: 5px;
}
.content {
display: flex;
flex-direction: column;
align-items: center;
padding: 5px;
.messages-list {
display: flex;
flex-direction: column;
overflow-y: auto;
/* What to add here to make it scrollable? */
.message {
height: 50px;
margin: 10px;
padding: 10px;
background: #1dc497;
}
}
}
}
}
How can I make messages list to scroll?
You have to set the height of .content to 100% and make it scrollable:
.page {
background-color: #ddd;
width: 300px;
height: 300px;
}
.page .messages-section {
display: flex;
flex-direction: column;
width: 50%;
height: 100%;
background-color: #ccc;
}
.page .messages-section .header {
background: #bbb;
padding: 5px;
}
.page .messages-section .content {
display: flex;
flex-direction: column;
align-items: center;
padding: 5px;
height: 100%;
overflow-x: scroll;
}
.page .messages-section .content .messages-list {
display: flex;
flex-direction: column;
overflow-y: auto;
/* What to add here to make it scrollable? */
}
.page .messages-section .content .messages-list .message {
height: 50px;
margin: 10px;
padding: 10px;
background: #1dc497;
}
<div class="page">
<div class="messages-section">
<div class="header">Your messages</div>
<div class="content">
<img src="https://http.cat/100" width="70" height="50" />
<div class="messages-list">
<div class="message">Hi.</div>
<div class="message">Hello.</div>
<div class="message">Good morning.</div>
<div class="message">Yo!</div>
</div>
</div>
</div>
</div>

How do I set 100% height of outer element for inner

I have a flexbox 'table' where I'm basically trying to put an interesting thing on the top. The problem I've encountered is being unable to write it in HTML
My current result
The result I'm trying to get
I have tried to do it without inner divs and spans, by doing margin:auto but unfortunately it relocates borders from the left and right to the middle :( So the code for the current result is:
.flex-container {
width: auto;
height: 100vh;
display: flex;
flex-direction: column;
}
.flex-container .middle {
flex: 1;
display: flex;
}
.top {
padding-top: 30px;
border: 2px solid #05788D;
display:flex;
}
.leftSide {
padding-top: 30px;
display: flex;
flex-wrap: wrap;
flex-basis: 50%;
overflow: auto;
border: 2px solid #05788D;
}
.rightSide {
padding-top: 30px;
display: flex;
flex-wrap: wrap;
flex-basis: 50%;
overflow: auto;
border: 2px solid #05788D;
border-left-style: none;
}
.firstOption
{
border: 2px solid #05788D;
border-top-style: none;
border-bottom-style:none;
}
.anotherOption
{
border: 2px solid #05788D;
border-top-style: none;
border-bottom-style:none;
border-left-style:none;
}
<div class="flex-container">
<div class="top">
<div style="width:50%;">
<span class="firstOption">One option</span>
</div>
<div style="width:50%;">
<span class="anotherOption">Another option</span>
</div>
</div>
<div class="middle">
<div class="leftSide">
left
</div>
<div class="rightSide">
right
</div>
</div>
</div>
Simply use text-align to control text-alignment of your span and use padding inside your span and don't forget to make them inline-block:
.flex-container {
width: auto;
height: 100vh;
display: flex;
flex-direction: column;
}
.flex-container .middle {
flex: 1;
display: flex;
}
.top {
border: 2px solid #05788D;
display: flex;
}
.top div {
flex:1;
}
.leftSide {
padding-top: 30px;
display: flex;
flex-wrap: wrap;
flex-basis: 50%;
overflow: auto;
border: 2px solid #05788D;
}
.rightSide{
display: flex;
flex-wrap: wrap;
flex-basis: 50%;
overflow: auto;
border: 2px solid #05788D;
border-left-style: none;
}
.firstOption {
text-align:right;
}
.firstOption span,.anotherOption span{
border: 2px solid #05788D;
padding-top: 30px;
display:inline-block;
}
<div class="flex-container">
<div class="top">
<div class="firstOption"><span>One option</span></div>
<div class="anotherOption"><span>Another option</span></div>
</div>
<div class="middle">
<div class="leftSide">
left
</div>
<div class="rightSide">
right
</div>
</div>
</div>
You've added padding-top: 30px to class="top". Instead, the inner child (which are 50%) should have padding-top:30px;
While of course this can be done in a better way, above is the quickest solution to your problem.
You could use justify-content: flex-end on the left option to make it position at the end of the div. I applied the suggested changes to your code in this fiddle.
I can really recommend this guide!

Flexbox: scrollable content with sticky footer

I want to make a box (flex-item in this case) which always stays in the middle of it's container. In that box, there is a header, footer and content section. If the size of the content grows too big in height, I want the content section to be scrollable. The header and footer should always be visible and the box should always stay in it's container.
Here is what I have been able to write:
HTML
<div class="flex-container">
<div class="flex-item">
<header>Header</header>
<div class="content">
A
<br>B
<br>C
<br>D
<br>E
<br>F
<br>G
<br>H
<br>I
<br>J
<br>K
</div>
<footer>Footer</footer>
</div>
</div>
CSS
body {
margin: 120px;
}
.flex-container {
display: flex;
width: 200px;
height: 200px; /* We can assume that the container's height is hardcoded in this example, but the end solution should work even if this value is changed*/
border: 1px solid black;
justify-content: center;
}
.flex-item {
box-sizing: border-box;
width: 150px;
border: 5px solid blue;
align-self: center;
background-color: red;
display: flex;
flex-flow: column;
max-height: 100%;
}
.content {
/* It should be possible to scroll this element when it get too big in height*/
background-color: grey;
flex: 1;
}
The code is hosted on JSFiddle: https://jsfiddle.net/9fduhpev/3/
To explain the same thing visually, here is the current situation:
Here is what I want:
Use overflow-y: auto;.
Read this: http://www.w3schools.com/cssref/css3_pr_overflow-y.asp
body {
margin: 120px;
}
.flex-container {
display: flex;
width: 200px;
height: 200px;
border: 1px solid black;
justify-content: center;
}
.flex-item {
box-sizing: border-box;
width: 150px;
border: 5px solid blue;
align-self: center;
background-color: red;
display: flex;
flex-flow: column;
max-height: 100%;
}
.content {
background-color: grey;
flex: 1;
overflow-y: auto;
}
<div class="flex-container">
<div class="flex-item">
<header>Header</header>
<div class="content">
A
<br>B
<br>C
<br>D
<br>E
<br>F
<br>G
<br>H
<br>I
<br>J
<br>K
<br>L
</div>
<footer>Footer</footer>
</div>
</div>
I suggest you give it overflow: auto. With that it will be scrollable when needed.
body {
margin: 20px;
}
.flex-container {
display: flex;
width: 200px;
height: 200px;
border: 1px solid black;
justify-content: center;
}
.flex-item {
box-sizing: border-box;
width: 150px;
border: 5px solid blue;
align-self: center;
background-color: red;
display: flex;
flex-flow: column;
max-height: 100%;
}
.content {
background-color: grey;
flex: 1;
overflow: auto;
}
<div class="flex-container">
<div class="flex-item">
<header>Header</header>
<div class="content">
A
<br>B
<br>C
<br>D
<br>E
<br>F
<br>G
<br>H
<br>I
<br>J
<br>K
<br>L
</div>
<footer>Footer</footer>
</div>
</div>
I would do something like this:
.content {
height: 100%;
overflow:auto;
background-color: grey;
flex: 1;
}
https://jsfiddle.net/9fduhpev/4/