Styling for overflowing 2 text containers side by side - javascript

Hi so I am styling something which displays both the user username and the title of the item on the same line, something along the lines of:
username / title (similar to github)
i want to style it such that if the full width of username / title is less than the container width, it should display the full text of both, but if they exceed the max width of the container and start to overflow i want them to keep to about a 50-50 or maybe 40-60 ratio with ellipsis, like this:
long_usern... / long_ti...
so far i've screwed around a bit with max-width and min-width and percentages, and i've ended up with this final state:
.username {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.title{
min-width: 50%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
https://jsfiddle.net/9csohvpa/4/
however when the title is too long sometimes it obscures the username to the point where it is only a few dots and does not hold any meaning.
... / super_duper_ultra_long...
sometimes it manages to still show a bit of the username while overflowing the rest of the long title, although i do not really understand how it works and how priority is given to each element in this case about how much of the full width it is allowed to take up. i'd like the username to take up at least 30-40% of the width no matter how long the text in each element is.
its fine if the solution gives a hard limit on the username like doesn't allow it to go over 40% width in the case of long username with short title that doesn't fill up the to max width because it looks a little silly with a long username and short title.
i've tried min-width for the username class but in the case of a short username there is a lot of blank space before the slash and i don't want that.
i / loveyou
i've also tried max-width 50-50 but with a short username and long title the title doesn't fill up the remainder of the space in the width of the flex container like i want it to
i / hateyousomu... |
| <-- maximum available width for container
username / long_title_na...|
|
i / hateyousomuch555 | <-- ideal solution
in any case, the ideal solution should manage to keep the elements at about an 40-60 ratio of the max-width when the sum of widths of both element exceeds the maximum available width of the container, but show the full width of text in both elements otherwise
Edit: Thanks #robbieAreBest for answering, and uncovering that adding width: fit-content to the .username class doesn't work for some reason (in fact it has no effect on the width of the class at all). Through this I uncovered that the percentage width the username section takes up in the container is directly proportional to its length, and the 50/50 ratio holds up only when the length of the username is about the same as the length of the title or longer (e.g. https://jsfiddle.net/pys25tfa/). Does anyone know why this happens or how to fix it? Would be greatly appreciated.
Edit 2 + existing solution I'm willing to make do with:
Solution has been found, but every solution has room for improvements. Current solution only considers the basic 4 cases I mentioned about and limits the username to about 40% of the total width even with a short title. If I missed out any possible combinations, if someone manages to find a case where my code breaks, or if someone manages to find a better solution which deals with long username/short title case better, please do let me know.
The ideal code (which may be a tad bit specific/unnecessary): Long username with long title that combined overflow the full width will limit the width of each element at 40/60 ratio respectively, but a long username and short title which does not overflow the full width limits the username to about 60% of the width instead, allowing more info to be displayed to the user. If anyone manages to find a solution which displays the full username in the case of long username and short title please do post below as well. Thanks all for your effort to help me :) I appreciate it very much.

I would add width: fit-content to your .username class
.username {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
width: fit-content;
}
.title{
min-width: 50%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
This should let the username shrink and give more space to your .title span while also taking up half the available area if needed.
EDIT AFTER COMMENT
If the above doesn't give you the results you are after you might want to try using grid display instead:
html:
<div class="wrap">
<span class="username">usern</span>
<span class="title"> / super_duper_long_title</span>
</div>
css:
.username {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.title{
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.wrap {
display: grid;
width: 150px;
grid-template-columns: auto minmax(20%,100%);
}
https://jsfiddle.net/eu2t0fq3/1/

Related

How to set width to min-content but allow words to be on the same line?

I have a div that contains text, but there is empty space around them by default. Setting the width to min-content solves this, but it means that each word will be on a separate line. If there is space for more than 1 word on 1 line, I need the words to stay be on one line.
Here is what things look like with without width: min-content:
As you can see, there is space around this for some reason and I can't figure out why. It's just a grid item/flex item and no css a part from font size and line height.
You can give reffer below code for achieving this.
You can try using white-space: pre-wrap; or white-space: nowrap; for your case
.my-text{
white-space: pre-wrap;
}
or
.my-text{
white-space: nowrap;
}
You can reffer here
I think max-width: fit-content; is what you need.

Problem with nested flex containers. Inner container's item is not respecting its parent's width [duplicate]

I have 4 flexbox columns and everything works fine, but when I add some text to a column and set it to a big font size, it is making the column wider than it should be due to the flex property.
I tried to use word-break: break-word and it helped, but still when I resize the column to a very small width, letters in the text are broken into multiple lines (one letter per line), and yet the column does not get smaller width than one letter size.
Watch this video
(at the start, the first column is the smallest, but when I resized the window, it is the widest column. I just want to respect flex settings always; flex sizes 1 : 3 : 4 : 4)
I know, setting font-size and column padding to smaller will help... but is there any other solution?
I can not use overflow-x: hidden.
JSFiddle
.container {
display: flex;
width: 100%
}
.col {
min-height: 200px;
padding: 30px;
word-break: break-word
}
.col1 {
flex: 1;
background: orange;
font-size: 80px
}
.col2 {
flex: 3;
background: yellow
}
.col3 {
flex: 4;
background: skyblue
}
.col4 {
flex: 4;
background: red
}
<div class="container">
<div class="col col1">Lorem ipsum dolor</div>
<div class="col col2">Lorem ipsum dolor</div>
<div class="col col3">Lorem ipsum dolor</div>
<div class="col col4">Lorem ipsum dolor</div>
</div>
The Automatic Minimum Size of Flex Items
You're encountering a flexbox default setting.
A flex item cannot be smaller than the size of its content along the main axis.
The defaults are...
min-width: auto
min-height: auto
...for flex items in row-direction and column-direction, respectively.
You can override these defaults by setting flex items to:
min-width: 0
min-height: 0
overflow: hidden (or any other value, except visible)
Flexbox Specification
4.5. Automatic Minimum Size of Flex
Items
To provide a more reasonable default minimum size for flex items, this
specification introduces a new auto value as the initial value of
the min-width and min-height properties defined in CSS 2.1.
With regard to the auto value...
On a flex item whose overflow is visible in the main axis, when specified on the flex item’s main-axis min-size property, specifies an automatic minimum size. It otherwise computes to 0.
In other words:
The min-width: auto and min-height: auto defaults apply only when overflow is visible.
If the overflow value is not visible, the value of the min-size property is 0.
Hence, overflow: hidden can be a substitute for min-width: 0 and min-height: 0.
and...
The minimum sizing algorithm applies only on the main axis.
For example, a flex item in a row-direction container does not get min-height: auto by default.
For a more detailed explanation see this post:
min-width rendering differently in flex-direction: row and flex-direction: column
You've applied min-width: 0 and the item still doesn't shrink?
Nested Flex Containers
If you're dealing with flex items on multiple levels of the HTML structure, it may be necessary to override the default min-width: auto / min-height: auto on items at higher levels.
Basically, a higher level flex item with min-width: auto can prevent shrinking on items nested below with min-width: 0.
Examples:
Flex item is not shrinking smaller than its content
Fitting child into parent
white-space css property is creating issues with flex
Browser Rendering Notes
Chrome vs. Firefox / Edge
Since at least 2017, it appears that Chrome is either (1) reverting back to the min-width: 0 / min-height: 0 defaults, or (2) automatically applying the 0 defaults in certain situations based on a mystery algorithm. (This could be what they call an intervention.) As a result, many people are seeing their layout (especially desired scrollbars) work as expected in Chrome, but not in Firefox / Edge. This issue is covered in more detail here: flex-shrink discrepancy between Firefox and Chrome
IE11
As noted in the spec, the auto value for the min-width and min-height properties is "new". This means that some browsers may still render a 0 value by default, because they implemented flex layout before the value was updated and because 0 is the initial value for min-width and min-height in CSS 2.1. One such browser is IE11. Other browsers have updated to the newer auto value as defined in the flexbox spec.
Revised Demo
.container {
display: flex;
}
.col {
min-height: 200px;
padding: 30px;
word-break: break-word
}
.col1 {
flex: 1;
background: orange;
font-size: 80px;
min-width: 0; /* NEW */
}
.col2 {
flex: 3;
background: yellow
}
.col3 {
flex: 4;
background: skyblue
}
.col4 {
flex: 4;
background: red
}
<div class="container">
<div class="col col1">Lorem ipsum dolor</div>
<div class="col col2">Lorem ipsum dolor</div>
<div class="col col3">Lorem ipsum dolor</div>
<div class="col col4">Lorem ipsum dolor</div>
</div>
jsFiddle
I'm finding this has bitten me repeatedly over the years for both flex and grid, so I'm going to suggest the following:
* { min-width: 0; min-height: 0; }
and then just use min-width: auto or min-height: auto if you need that behaviour.
In fact, throw in box-sizing as well to make all layout more sane:
* { box-sizing: border-box; min-width: 0; min-height: 0; }
Does anyone know if there are any odd consequences? I've not encountered anything in several years of using a mix of the above. In fact, I can't think of any cases where I'd want to layout from content outwards to the flex/grid, rather than flex/grid inwards to the content --- and surely if they exist, they're rare. So this feels like a bad default. But maybe I'm missing something?
The pure answer to your question is that by default, browsers tend to display as much information as possible to the reader (and not to hide anything).
That happens by default, and even includes showing default black color fonts on a white background (for maximum page contrast and readability), adding a scroll bar where content is larger than the viewport height (or width) or still showing content from a markup (or the background color) even if this was mistakenly placed after </body> or even </html> tags in the html file.
In context of CSS, this applies as well, but you also are allowed to play with many customizations on top of that.
Even in a screen if using a huge font (like font-size: 50em;) this initially acts as an overflowing element (and placing the font inside a flexible child container by using display: flex doesn't change this default behaviour unless you use overflow: hidden or resize the element in some way.
An elegant solution is to use a dynamic resizing of the letters, for example
font-size: calc(0.5em + 2vw)
which works great even in a responsive scenario.
As a previous answer mentioned, A flex item cannot be smaller than the size of its content along the main axis (for the same reason, that is not only specific to the flexbox model implemented in CSS but because of the inner browser way of working). Even a long word is displayed with a scrollbar if it's longer than display width as if being a block type element with a fixed size instead.
This is mentioned in old html 4.01 specifications as
"By convention, visual HTML user agents wrap text lines to fit within
the available margins. Wrapping algorithms depend on the script being
formatted.
In Western scripts, for example, text should only be wrapped at white
space. "
as seen here in paragraph 9.5.3. This means that, since then, the text had to be continuously displayed by default (unless we decide to split it but not at single character level: a single non-white character shown at 120em size will trigger scrollbars displaying on the browser).
Words are also clearly defined in paragraph 9.1 in the same source:
we use the term "word" here to mean "sequences of non-white space
characters"
The purpose of displaying the original format of any word is to not destroy, hide or distort the original information, the meaning or intent of the code author. As such, we also have for keeping in same line two words that are connected - when breaking them might be disruptive (such as New York, 10 PM, 10 km/h, § 10, etc)
For this code below, adding width: 100% solved my problem.
.post-cover .inner {
display: flex;
flex-direction: column;
flex-wrap: wrap;
justify-content: center;
align-content: flex-start;
align-items: flex-start;
word-break: break-all;
z-index: 21;
}
.post-cover .article-page {
padding: 20px 0;
margin-bottom: 40px;
font-size: 0.875em;
line-height: 2.0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
width: 100%; /* Add this */
}
I tried everything, even putting the below code in the index.css.
* {
min-width: 0;
min-height: 0;
box-sizing: border-box;
}
But nothing worked.
finally I made the div I wanted to shrink past it's content to have position: absolute;. Then it started shrinking.
It's parent div would need a defined height and width. This might not be the best solution for every scenario but if this works for you, good!

Most reliable way to detect when element overflows print width

I have a <table> where users customize the number of elements, font, and font size, and users often print the table. If the table is too wide to fit on a single printed page, some columns get cut off and the user may not realize until later, at which point the user is upset.
Is there a good way to detect when the table overflows the print width so I can warn the user? I know that the proper answer is "web browsers were not designed for printing, you can't do that", so I'm happy with a hack. Right now I use jQuery outerWidth() to see if the width is greater than 700px. Is there a better way?
The best way is to use a media print css style sheet where you specify the max width of the table, and make sure that you use table-layout:fixed;. Additionally you can set word-wrap in such a way that everything breaks nicely when you deal with large input.
#media print {
html{
width: 100%;
max-width: 700px;
}
.toprinttable {
font-size: 11px;
max-width: 700px;
border: 0;
table-layout:fixed; /*This is important*/
word-wrap:break-word;
border-collapse:collapse;
}
}

Text truncation based on cell width

I need javascript solution for ellipsis text truncation.
There is a percentage table which can be re-sized according to the screen resolution. While re-sizing the screen, when the table cell reached 20px it should truncate the text inside it. Which means it should not decrease the width below 20px.
I have done this using css solution (ellipsis) but unfortunately it is not widely supported for all browsers So I am looking for pure java-script solution to truncate the text by calculating the cell width.
here is how I am using css for this
td{
background:#cccc33;
text-overflow: ellipsis;
white-space: nowrap;
width: auto;
max-width: 20px;
overflow: hidden;
}
DEMO

If the text doesn't fit on the same row don't display all

I have a left sidebar on my website which contains a list with links. If one link is very long, it won't fit on only one row.
For example: 'This is a very long long long link'.
What can I do to display as much as posible from this text (eg. 'This is a very long') but in such a way that it will fit on only one row (one row has 200px width)?
Set the CSS to:
overflow:hidden;
white-space:nowrap;
There is a CSS3 property called text-overflow that controls just what you describe. In combination with overflow: hidden; and white-space: nowrap; you can customize what is displayed at the end of the line.
There's documentation here that's good and describes the property's flexibility. But let's say all you want to do is add an ellipsis (…) to the end of lines that exceed their width, then all you have to write is :
.sidebar p { /*Or whatever selector matches*/
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
Apply overflow: hidden; on the container, along with a set width and height.

Categories