Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[css-sizing] How to shrink to fit the width? #191

Open
yisibl opened this issue Jun 15, 2016 · 24 comments
Open

[css-sizing] How to shrink to fit the width? #191

yisibl opened this issue Jun 15, 2016 · 24 comments
Assignees

Comments

@yisibl
Copy link
Contributor

yisibl commented Jun 15, 2016

In this demo: http://jsbin.com/weqapufoyi/edit?html,css,output

demo

Because span float will automatically wrap, how to make the parent element shrink to the "Expectation" effect.

Can we add a new width/height value(e.g. width: auto-shrink), or already have other solutions?

spec: https://drafts.csswg.org/css-sizing/#width-height-keywords

cc @dholbert @tabatkins @fantasai

@SebastianZ
Copy link
Contributor

I think the best would be to adjust fit-content (in combination with max-width/max-height) and fit-content() accordingly to shrink automatically to the size of the content.

Sebastian

@yisibl
Copy link
Contributor Author

yisibl commented Jun 15, 2016

@SebastianZ That would be best.

@tabatkins
Copy link
Member

No, fit-content() won't work here. fit-content is "try to be max-content size, clamped by min-content and the specified limit" (or in the case of the fit-content keyword, clamped above by the available space). So using fit-content() will still make it the full size with empty space, as shown in the first example. You can see this behavior today in floats - create a float containing a few very long words, and when they break, the float doesn't "tightly wrap".

Tight wrapping has been discussed in the past, but has never made it in yet.

@fantasai
Copy link
Collaborator

fantasai commented Aug 2, 2016

On 06/22/2016 02:10 AM, Tab Atkins Jr. wrote:

Tight wrapping has been discussed in the past, but has never made it in yet.

See discussion at https://www.w3.org/mid/54DAAD2C.6060704@inkedblade.net

~fantasai

@vasilisvg
Copy link

I have the same issue on one of my sites, as I tried to explain here. And today the CSSWG Twitter account told me that it’s been discussed here on Github. Hurray! I was wondering, is there any progress on this?

@fantasai
Copy link
Collaborator

fantasai commented Feb 17, 2017

No progress yet, though we're glad to have your use cases tracked here. :) I think the blocker here will be largely the difficulty for implementations in doing something relatively difficult and expensive, so seeing where it's needed is helpful to justify the effort.

@Nadya678
Copy link

Please add this option. I also need it. JS solution is complicated because during resizing window there must be made additional steps...

@benface
Copy link

benface commented Nov 21, 2018

I love that some problems like this one still don't have a solution with today's CSS. Does it represent a challenge (cyclic dependencies)? Does it lack use cases / demand from developers?

Here's a use case I had today: https://codepen.io/benface/pen/WYMMPo

I don't want the underline to go past the text. Easy when the text doesn't wrap (a simple display: flex; on the container takes care of that), but impossible when it does.

I'll be following this one for sure.

@tabatkins
Copy link
Member

Yes, it's cyclic in general - the container size depends on the layout of children, but children layout depends on the size of the container.

In restricted cases you can of course solve this, but not in general.

@Dan503
Copy link

Dan503 commented May 25, 2019

I run into the issue constantly when building site navigation. 😫😢

navigation-text-wrapping-example

Codepen of the screenshot found here:
https://codepen.io/daniel-tonon/pen/QRrNGY

Note: I use width: min-content to get the desired look in this example but that is not a good solution to the problem at large.

@argyleink
Copy link
Contributor

  • adding a <br> can hint enough to the browser to shrink wrap after line wrapping, but that's not viable for responsive text.
  • wrapping flex layouts can leave unwanted space in a container (see boxes example in codepen demo)
  • even ellipsing the text, so no wrapping occurs, still struggles to shrink wrap after it's task is done.

Screenshot 2023-03-03 at 7 40 31 AM

https://codepen.io/argyleink/pen/wvjeOdz


What I believe we want is shrink wrapping, and i mean that in a tricky way, we want it to shrink the inline size to fit the content AFTER wrapping has occurred. Some way to specify this inline-size or post-wrapping task would be really nice.

@kizu
Copy link
Member

kizu commented Mar 3, 2023

Just want to drop here that this is something I also always wanted.

One thing I want to add — when looking and playing with text-wrap: balance, I think what it does/needs to do can be tightly related to this, and maybe if this was to move forward, we could start with the implementation that could have a similar restriction of the “number of lines” that would be checked?

This way, it won't be super perf intensive for more complex cases, but would be simple enough to handle for most of the cases where you'd want it (usually the more there is content, the more likely it would take the full width when wrapping).

Related issues: #8516 and #3070, as I think this one and those two have the similarities in the possible limitations.

@simevidas
Copy link
Contributor

Related discussion on Reddit:

https://www.reddit.com/r/css/comments/16c9gmh/how_can_i_remove_this_horizontal_spacing_when_a/

How can I remove this horizontal spacing when a message is multi line

@kizu
Copy link
Member

kizu commented Dec 7, 2023

I just published an article that explores how anchor positioning can be used to partially solve these kinds of issues: https://kizu.dev/shrinkwrap-problem/

So, when anchor positioning eventually becomes available, it will help with some use cases. Not all of them — there is still room to explore how the proper native solution could look like. But my exploration of this did show that it is very far from being a trivial problem, and when involving more complicated code it is easy to end up with circularity issues (hence, why we don't have any good way of handling this yet).

@benface
Copy link

benface commented Dec 7, 2023

That is awesome, @kizu! Great work.

@tomasdev
Copy link

tomasdev commented Jan 25, 2024

Similar issue here, but inverted in a way...

Current:

<style>
body { font-family: sans-serif; }
.box {
  border: 1px solid red;
  display: grid;
  grid-template-columns: min-content max-content auto;
  gap: 16px;
  width: 360px;
}
.a {
  background: #0f03;
}
.b {
  background: #00f3;
}
.c {
  background: #f0f3;
  justify-self: end;
}
</style>

<div class="box">
  <div class="a">sometimes longestwordever I become so long it is annoying</div>
  <div class="b">No Shrink</div>
  <div class="c">No Shrink</div>
</div>

Screenshot 2024-01-25 at 6 16 20 PM

Expectation (wrapping happens when the word wouldn't fit even if container used all available space):

Screenshot 2024-01-25 at 6 19 51 PM

@Dan503
Copy link

Dan503 commented Jan 26, 2024

@tomasdev I don't understand what you are advocating for in your expectation.

There is no logical reason for the text to wrap at the point it does in your expectation.

It wraps the way it does currently because min-content shrinks the container to the smallest width possible without causing content to overflow out of the box.

@Loirooriol
Copy link
Contributor

@tomasdev It sounds lke you want

grid-template-columns: minmax(min-content, max-content) max-content auto;

That's unrelated to the problem here.

@tomasdev
Copy link

tomasdev commented Jan 26, 2024

So why couldn't implementing width: minmax(min-content, max-content); be the solution for the original issue?

EDIT: It doesn't work for my use case. Expanding the container width does not put more words where they fit:

Screenshot 2024-01-25 at 8 19 44 PM

I believe it is still the same issue.

@Loirooriol
Copy link
Contributor

It's hard to tell what you want, your "inverted in a way" might have mislead me. If you want

  • some size between min-content and max-content
  • but sizing tightly to the longest sequence of words that fits within that tentative size

Then the 1st part works with minmax(min-content, max-content) (I have just tested in Gecko, Blink and WebKit), but the 2nd part is this issue indeed and is not provided by minmax(min-content, max-content).

@LeaVerou
Copy link
Member

I’ve been using text-wrap: balance for a while now, and this issue severely restricts its utility to basically elements whose box is not visible (no backgrounds, no borders, etc.). For elements with a visible box, not only is this undesirable in practically every case I have come across, it is also incredibly hard to work around.

Not sure it's useful at this point, but here is another testcase: https://codepen.io/leaverou/pen/MWRZVJv

FWIW, I had also expected fit-content would do the reasonable thing here, and was surprised it did not.

@kizu
Copy link
Member

kizu commented Apr 24, 2024

Made another small demo using my anchor positioning way of doing the shrinkwrap (so obviously only visible in Chrome Canary): https://codepen.io/kizu/pen/LYvqPmO?editors=1010

Here is a video, showing 5 items, each having a max-width of 20% of the parent's width, with text-wrap: balance on them, and placed so every item follows the previous one:

Screen.Recording.2024-04-24.at.11.22.45.mov

With this method (and I imagine with any other similar one), for every element with shrinkwrap we need to know its dimensions before layout out every other element that depends on it. This can lead to very complex calculations if used for many elements, which is probably one of the reasons this does not exist in CSS yet (and I doubt it could, but we can dream, I guess).

@vincerubinetti
Copy link

I just published an article that explores how anchor positioning can be used to partially solve these kinds of issues: https://kizu.dev/shrinkwrap-problem/

This was a very interesting and creative article, but still too hacky and un-supported for me to use in real use cases.

I would highly recommend anyone stumbling on this issue to use this (pretty simple and clean) JS-only solution for now:
https://stackoverflow.com/questions/14596213/shrink-div-to-text-thats-wrapped-to-its-max-width/78307608#78307608

@TomerAberbach
Copy link

Was going to switch from react-wrap-balancer to native text-wrap: balance;, but couldn't because of this issue:

https://x.com/TomerAberbach/status/1786804007341638049

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests