When text gets in two lines
I am always running into this problem.
Lets say i have a button which is display: inline-block (or flex, or inline-flex) and max-width: fit-content;
As long as the inner text does not break into two lines it looks good. The width of the button is defined by its text. When the text breaks in two lines the button gets width 100%. I want it to fit the content. Any ideas what to do? I cannot use max-width because its a cms and i dont know what text will be inside.
41 Replies
After research it seems there is no css solution for this.
The text behaviour is really weird. It should not become block-element when becoming multi-lines.
So the only solution seems to be via JS: I check the height and inject a <br> inbetween. That is so stupid
I made a codepen:
https://codepen.io/ollio/pen/poMGVWQ
it has to do with
text-wrap: balance;
Apparently, for Reasons™️, the element isn't shrink wrapped when you use balance: https://developer.chrome.com/docs/css-ui/css-text-wrap-balance
Balancing won’t change the inline-size of the element There's an advantage to some of the JavaScript solutions for balanced text wrapping, as they change the max-width of the containing element itself. This has an added bonus of being "shrink wrapped" to the balanced block. text-wrap: balance does not have this effect and can be seen in this example:
See how the width shown from DevTools has a bunch of extra space at the end? That's because it's a wrapping style only, not a size changing style. Because of this, there's a few scenarios where text-wrap: balance isn't that great, at least in my opinion. For example, headings inside of a card (or any container with borders or shadows).
Turning text-wrap:balance off does not change the behaviour:
the button still is 100% width
balance doesn't recalculate the width after balancing the text. The top one is full width because there's room for the text. With balance on, it's still pretending the text is there, but it's moving the words nonetheless
Basically I'm just saying you're right, there's no css solution
lol
🙂
The article just explains why
that is really sad
ty
Np, I learned something too
Indeed an interesting case. I was dealing with content sensitive demands here and there, mostly realizing that it may not be a job for CSS but needs to be solved either by design or actual programming.
Limiting the label's inline-space with magic numbers (20ch) would be the "best" CSS can do, other than that I am clueless aswell.
That balance renders a block is unfortunate ...lol
Thanks for sharing 🙆
That is something that should be implemented in future css!
To clarify, it's not changing the rendering mode of the element, it's simply determining the size of the element before it balances the text, and not recalculating after balancing. I'm sure there's some kind of valid reason for this, either performance wise (this is apparently an expensive computation) or logistically, but the display property is untouched in this case.
Not sure if we are really talking about the same. I removed text-wrap: balance. To emphasize i changed the wording. Why does the first button behaves like a block element when the inner text is too long for one line?
It's not behaving like a block element because of balance. Balance just isn't shrinking the container when it does the balancing. This has nothing to do with the display value and it doesn't change at all
It's how flexbox operates, innit?
This isn't due to flex box either. It's just a quirk of text wrap balance
but there is no text-wrap: balance!
In this one?
yes. i updated the codepen and made a second Button-Set below. No text-wrap:balance, no flexbox. Why does the button gets 100% width?
The pen got updated.
– But doesn't
flex
fill up the hypothetical space to push the children apart and/or do flexy stuff? I do see that comparing it to block is not correct 🥲
imo in any case as for now you may be forced to limit the parent element's max-width
to let the children act on it (this should also allow text-wrap
to do its job?). Maybe with rules applied by javascript if there is a need for different stylings between single-and multi-line buttons. But I could be wrong ofc.I think it is just a strange behaviour of multiline text. IDK. My problem is that i am developing CMS Systems and the content is entered by the editors. And i am always asked to resolve this problem. Here is a nice live-example:
They ask me why the 3rd button is so wide...
The html is div > span. Div has no css properties, Span is set to inline-block. If i set it to inline it looks really weird:
Same here. Just a Textbox with an arrow:
If text gets multiline:
They ask me to move the arrow next to the text
In this case i could use display inline / inline-block but loose the positioning features of flexbox
Well, thats a design issue imo ...
It would be strange if the multi-line click area is more narrow than the others, given these are listed vertically, no? Moving the arrow next to the text would either cause a large white-space clickable area on it's right that is not visible, or the design to be inconsitent. This could perhaps be solved by adding background and/or borders to make the click-area more obvious.
In the case of buttons maybe centering them horizontally would make it look more coherent
In the second case there is always just one Button with arrow. The problem only gets visible on mobile. People dont see the arrow (because it is too far from the text, they say) I can live with that 🙂
The Orange-Button: The design is not made by myself. I am not allowed to center them
I'm pretty sure that's just how fit-content works. It wraps the content as best as possible, but at the same time with inline text content it'll take as much room as it can
yes. I thought there maybe is a solution for this. But maybe not
the only way to accomplish this with CSS, is with
text-wrap: balance;
and that has the issue described earlieryes. so i have to tell them the internet (browsers) have no solution for this (seemingly easy) problem
Maybe Kevin has an idea 😉
-# Edit 20241115: caution, calculation fails with box-sizing: border-box
I have stolen a thing https://jsfiddle.net/d63Lpshg/
_
I just looked at the link you provided. https://jsfiddle.net/d63Lpshg/
That is a neat way to resolve this problem with JS. Gonna try that
Many thanks!
Edit fiddle - JSFiddle - Code Playground
JSFiddle - Test your JavaScript, CSS, HTML or CoffeeScript online with JSFiddle.
I never worked with createRange()
not sure if it targets the right thing, but eventually you can use bits of it ... lol
yes think so.
Also: Many thanks for your patience guys 😉
I modified the JS a little bit and it works 🙂