CSS white-space nowrap expand flexbox's child width - html

I'm learning CSS and I'm having a problem with text-overflow. I have a flex-box with two child. I want child 2 fit into its parent and the text-content will be cut if it too long. But when I add white-space: nowrap to text then child-2 width is expanded. What did I do wrong here ?
.parent {
display: flex;
flex-wrap: nowrap;
max-width: 200px;
margin-right: 20px;
margin-bottom: 20px;
padding: 15px;
border: 1px solid black;
}
.child-1 {
white-space: nowrap;
border: 1px solid black;
margin-right: 20px;
}
.text {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
border: 1px solid red;
}
<div class="parent">
<div class="child-1">This is child 1</div>
<div class="child-2">
<div class="text">A really long long long long text</div>
<div class="text">Another really long long long long text</div>
</div>
</div>

That's what white-space: nowrap does - it stops the text from breaking at white space and wrapping to a new line.
Your .parent is set at a max-width: 200px so child-2 it cannot grow to to fit the longer text, and the single line is too long to fit into the space beside child-1, so it has to extend outside the parent - there is nowhere else for it to go.
I presume what you want to do is hide the part of the text that is extending out from the parent?
To do that you can use overflow to hide any content that extends outside of the child-2 div like this:
.child-2 { overflow:hidden; }
See more about the overflow property here: Mozilla MDN Web Docs
Example hiding the overflow:
.parent {
display: flex;
flex-wrap: nowrap;
max-width: 200px;
margin-right: 20px;
margin-bottom: 20px;
padding: 15px;
border: 1px solid black;
}
.child-2{
overflow:hidden;
}
.child-1 {
white-space: nowrap;
border: 1px solid black;
margin-right: 20px;
}
.text {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
border: 1px solid red;
}
<div class="parent">
<div class="child-1">This is child 1</div>
<div class="child-2">
<div class="text">A really long long long long text</div>
<div class="text">Another really long long long long text</div>
</div>
</div>

Related

Element is not 100% width in div

I have a div with some elements. I want these elements to be 100% width of the container div.
.container {
height: 100px;
width: 100px;
display: flex;
flex-direction: column;
overflow: scroll;
border: 1px solid black;
}
.inner {
width: 100%;
background-color: gray;
white-space: nowrap;
}
<div class="container">
<span class="inner">LONG TEXT LONG TEXT LONG TEXT LONG TEXT LONG TEXT</span>
<span class="inner">XXX</span>
<span class="inner">XXX</span>
</div>
As you can see if you horizontally scroll, the background is not 100% complete.
update your code like below:
.container {
height: 100px;
width: 100px;
display: flex;
flex-direction: column;
overflow: scroll;
border: 1px solid black;
align-items:flex-start; /* disable the stretch alignment*/
}
.inner {
min-width: 100%; /* min-width instead of width*/
background-color: gray;
white-space: nowrap;
}
<div class="container">
<span class="inner">LONG TEXT LONG TEXT LONG TEXT LONG TEXT LONG TEXT</span>
<span class="inner">XXX</span>
<span class="inner">XXX</span>
</div>
Or like below if you want all elements to get full coloration
.container {
height: 100px;
width: 100px;
overflow: scroll;
border: 1px solid black;
}
.container>div {
min-width: 100%;
display: inline-block;
}
.inner {
display:block;
background-color: gray;
white-space: nowrap;
}
<div class="container">
<div>
<span class="inner">LONG TEXT LONG TEXT LONG TEXT LONG TEXT LONG TEXT</span>
<span class="inner">XXX</span>
<span class="inner">XXX</span>
</div>
</div>
Here's the flex solution.
Replace flex-direction: column with flex-flow: column wrap in .container. And remove width: 100% from .inner.
And you get the desired result.
.container {
height: 100px;
width: 100px;
display: flex;
/*flex-direction: column;*/
flex-flow: column wrap;
overflow: scroll;
border: 1px solid black;
}
.inner {
/*width: 100%;*/
background-color: gray;
white-space: nowrap;
}
<div class="container">
<span class="inner">LONG TEXT LONG TEXT LONG TEXT LONG TEXT LONG TEXT</span>
<span class="inner">XXX</span>
<span class="inner">XXX</span>
</div>
UPDATE: I have came up with this non-flexbox solution (A curiosity driven actioin) Initially I misunderstood the question.
SOLUTION 1: Adding a wrapper div around your spans.
.container {
height: 100px;
width: 100px;
border: 1px solid black;
overflow-x:scroll;
}
.wrapper{
background:orange;
height:auto;
width:max-content;
}
.inner{
display:block;
min-width:100px;
}
<div class="container">
<div class="wrapper">
<span class="inner">LONG TEXT LONG TEXT LONG TEXT LONG TEXT LONG TEXT</span>
<span class="inner">XXX</span>
<span class="inner">XXX</span>
</div>
</div>
Just put a display: block in the span elements because their default display is inline, and that's why they behave the way they are behaving,

Fixed, match content and fill in same flex container [duplicate]

This question already has answers here:
Why don't flex items shrink past content size?
(5 answers)
Closed 4 years ago.
I would like to make the following layout:
<div class="main">
<div class="container">
<div class="first">
fixed size
</div>
<div class="second">
<span>very very very very very very very long text</span>
<span>other text</span>
</div>
<div class="third">
1000000000000000
</div>
</div>
</div>
to look like this:
Container should have three divs inside:
first div with fixed size
third div with width matching content
second div filling the remaining container witdh. Inside that div there are two spans. The first span should be the same with as it's parent and contain very long line of text that should be dotted if it cannot fit.
I tried the following css code:
* {
box-sizing: border-box;
}
.main {
width: 500px;
height: 500px;
border: 1px solid black;
padding: 10px;
}
.container {
display: flex;
width: 100%;
}
.container div {
display: flex;
border: 1px solid black;
}
.first {
flex: 0 0 100px;
}
.second {
flex-direction: column;
flex: 1;
}
span {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
border: 1px solid black;
}
.third {
flex: 0 1 auto;
}
but the result is not as I would like because the elements are overflowing outside of container and long text is not dotted.
What should I changed in my css to make this work?
Demo: https://stackblitz.com/edit/js-vnr21c
You need to set min-width:0 on the span's parent
* {
box-sizing: border-box;
}
.main {
width: 500px;
height: 500px;
border: 1px solid black;
padding: 10px;
}
.container {
display: flex;
}
.container div {
border: 1px solid black;
}
.first {
flex: 0 0 100px;
}
.second {
display: flex;
flex-direction: column;
min-width: 0;
}
span:first-child {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
border: 1px solid black;
}
.third {
flex: 0 1 auto;
}
<div class="main">
<div class="container">
<div class="first">
fixed size
</div>
<div class="second">
<span>very very very very very very very very long text</span>
<span>other text</span>
</div>
<div class="third">
1000000000000000
</div>
</div>
</div>

CSS to create a div that takes remaining width of parent when the other sibling div is as wide as it's content?

How do I go about creating the next layout :
Two divs share the width of a common parent. both of them display text content in a single line, while -
The div on the right is as wide as it's text content
The div on the left takes up all the remaining width of the parent and uses text-overflow: ellipsis to display '...' where the text gets cut.
Here is what I think I know about how it should be implemented -
.parent {
width: 400px;
height: 200px;
}
.left {
display: block;
white-space: nowrap;
text-overflow: ellipsis;
overflow: none;
}
.right {
display: inline-block;
}
<div class='parant'>
<div class='left'> This div should display all text content possible without line-breaking and display '...' where its being cut </div>
<div class='right'> This div is as wide as its text content </div>
</div>
It should look like this example
You can use Flexbox for this, just set display: flex on parent and flex-shrink: 0 on right element.
.parent {
width: 400px;
height: 200px;
display: flex;
}
.left {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
background: red;
}
.right {
background: lightblue;
flex-shrink: 0;
}
<div class='parent'>
<div class='left'> This div should display all text content possible without line-breaking and display '...' where its being cut </div>
<div class='right'> This div is as wide as its text content </div>
</div>
I think it's better using Flexbox for this. You should give display: flex; to .parent and flex:1; to .left. That will do your trick and it will not over flow the parent width also.
.parent {
width: 100%;
height: 200px;
display: flex;
}
.left {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
background: pink;
flex:1;
}
.right {
background: green;
}
<div class='parent'>
<div class='left'> This div should display all text content possible without line-breaking and display '...' where its being cut </div>
<div class='right'> This div is as wide as its text content </div>
</div>
try this
.parent {
width: 300px;
height: 200px;
overflow: hidden;
display: flex;
}
.left {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.right {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
<div class='parent'>
<div class='left'> This div should display all text content possible without line-breaking and display '...' where its being cut </div>
<div class='right'> This div is as wide as its text content </div>
</div>
**
You can use flexbox for your requirement. It is really simple and it will work like any other display properties. You can check this codepen link. This works 100%.
CSS
.container {
display: flex;
max-width: 500px;
border: 1px solid #ddd;
padding: 5px;
}
.one,
.two {
flex-grow: 1;
word-break: break-all;
padding: 10px;
color: #fff;
}
.one {
background-color: red;
}
.two {
background-color: blue;
}

Center div on wrapping (when it doesn't fit on the line)

I am trying to create this layout using only CSS:
When title fits:
When title doesn't fit:
The btn on the right should be centered if it wraps.
I tried this:
.container {
width: 100%;
border: 1px solid grey;
padding: 5px;
}
.block {
padding: 5px;
border: 1px solid orange;
float: left;
}
.right-block {
float: right;
}
<div class="container">
<div class="block">Logo</div>
<div class="block">Title that is too long</div>
<div class="block right-block">right-btn</div>
<div style="clear: both"></div>
</div>
But obviously, the btn is still on the right after it wraps. Any idea how to center it when it wraps ? And I'd like to avoid javascript.
Fiddle here: http://jsfiddle.net/b7rvhwqg/
Pure CSS solution using a flexbox layout:
Updated Example Here
The trick is to add justify-content: center/flex-wrap: wrap to the parent .container element for horizontal centering. Then adjust the first element's margin-right value to auto in order to prevent the last element from being centered when it's on the same line.
(You may need to resize the browser to see how it adjusts).
.container {
width: 100%;
border: 1px solid grey;
padding: 5px;
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.logo-text {
display: flex;
margin-right: auto;
}
.block {
padding: 5px;
border: 1px solid orange;
}
.center-block {
white-space: nowrap;
margin-right: auto;
}
<div class="container">
<div class="logo-text">
<div class="block logo">Logo</div>
<div class="block text">This title is short.</div>
</div>
<div class="block right-block">right-btn</div>
</div>
<div class="container">
<div class="logo-text">
<div class="block logo">Logo</div>
<div class="block text">This title is slightly longer than the other one. This title is longer than the other one...</div>
</div>
<div class="block right-block">right-btn</div>
</div>
There is an issue to achieve this via Pure CSS. The div is already having a float and you want to have a "long title" to accommodate that float and at the same time, you want the other right float to jump and become center. This is currently not possible. I believe, you need to consider media queries, but again, that will be a dependent solution, but your title looks like independent of expanding/contracting.
is it ok for you if the title will just fit depending on what width u want?.. for example:
{Logo}Title is toooooooooooooooooooooooooooooooooolong {btn}
it will become like this:
{Logo}Title is tooo... {btn}
it will be cut, then only ". . ." will continue
Flexbox is the most suitable for this task:
<div class="container">
<div class="block logo">Logo</div>
<div class="block title">Title that is too long Title that is too long</div>
<div class="block right-block">right-btn</div>
<div style="clear: both"></div>
</div>
.container {
display: flex;
flex-wrap: wrap;
width: 100%
border: 1px solid grey;
}
.block.logo {
flex-grow: 1;
border: 1px solid orange;
}
.block.title{
flex-grow: 10;
border: 1px solid orange;
}
.right-block {
flex-grow: 1;
border: 1px solid orange;
text-align: center;
}
http://jsfiddle.net/gmrash/7b8w982t/
.container {
width: 100%;
border: 1px solid grey;
padding: 5px;
}
.block {
padding: 5px;
border: 1px solid orange;
float: left;
}
.ellipsis{
text-overflow: ellipsis;
/* Required for text-overflow to do anything */
white-space: nowrap;
overflow: hidden; width: 75%;
}
.right-block {
float: right;
}
<div class="container">
<div class="block">Logo</div>
<div class="block ellipsis">Title that is too long Title that is too long Title that is too long that is too long Title that is too long</div>
<div class="block right-block">right-btn</div>
<div style="clear: both"></div>
</div>
jsFiddle

Constrain inline-block element's width to fit parent's for ellipsis

I'm trying to have an ellipsis effect on text contained into an inline-block element.
It HAS to be an "inline-block" element
The "width" can ONLY be set on its parent
Here is the HTML :
<div class="container">
<div class="icon"></div>
<div class="line">This is a much tooooooooooooooooo long line</div>
</div>
And the CSS :
.container {
border: solid 1px black;
background-color: lightgrey;
white-space: nowrap;
padding: 10px;
width: 200px;
}
.icon {
border: solid 1px blue;
display: inline-block;
width: 16px;
height: 16px;
}
.line {
border: solid 1px red;
display: inline-block;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
See. jsfiddle
Of course it works by setting a width on the line or by setting its display to block, but this is a no-no for my use case. I'm stuck there, any idea ?
Edit: Oh, I should have specified that the begining of the line is supposed to have some other inline-block elements (actually indentation and icon for a treeview) therefore, the width of the text container cannot be 100% of its parent...
.container {
border: solid 1px black;
background-color: lightgrey;
padding: 10px;
width: 200px;
}
.line {
border: solid 1px red;
display: inline-block;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 100%;
}
<div class="container">
<div class="line">This is a much tooooooooooooooooo long line</div>
</div>
UPDATE:
For the case with icon on left you can use calc as following:
.container {
border: solid 1px black;
background-color: lightgrey;
white-space: nowrap;
padding: 10px;
width: 200px;
}
.icon {
border: solid 1px blue;
display: inline-block;
width: 16px;
height: 16px;
}
.line {
border: solid 1px red;
display: inline-block;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: calc(100% - 16px);
}
<div class="container">
<div class="icon"></div>
<div class="line">This is a much tooooooooooooooooo long line</div>
</div>
You can simply do it using display: inline-flex in the container, without any need to use the display attribute with the icon and the line:
.container {
border: solid 1px black;
background-color: lightgrey;
white-space: nowrap;
padding: 10px;
width: 200px;
display: inline-flex;
}
.icon {
border: solid 1px blue;
width: 16px;
height: 16px;
}
.line {
border: solid 1px red;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
<div class="container">
<div class="icon"></div>
<div class="line">This is a much tooooooooooooooooo long line</div>
</div>