-
Notifications
You must be signed in to change notification settings - Fork 707
[css-fonts-5] Feature for making text always fit the width of its parent #2528
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
Comments
This requires performing layout in a loop, which we generally have avoided. Requiring a round-trip through JS is valuable because authors are more likely to realize it has a large perf cost |
In the JS at https://tobireif.com/ I perform two passes - that's plenty for a good-enough result, and it doesn't impact perf in any noticeable way (the text-fitting is only done once in addition to the first main run). That could be a great option for browser implementers as well, and it shows that supporting such a CSS feature is very feasible. |
If this were a feature, I think it'd be best if it was a CSS function. (similar to Something like I think using a function, other than being useful for minimum and maximum sizes, relays the gravity of using the feature since surely it'll have some performance issues in extreme cases. I'd love to see this in CSS! |
Great suggestions! A lower limit and an upper limit both make sense. Instead of |
Changing font-stretch, especially using variable fonts, is another way to fit text into parent. Or compression during justification . So if there is a css property that instructs layout engine to fit, it should allow different methods and so likely be separate from font-size. And this kind of functionality may not only be on line operation. It may be useful for more advanced functionality, like optimal paragraph layout, line clamping, or simple ellipsis. |
True! (also eg letter-spacing)
Let's start simple 😀 If we're asking for too much we might not get anything. The basic simple use case of fitting one line of text (eg a heading) into its responsive parent is so common that a solution for that would cover a lot (and more could get added/specd later). |
Yes it's feasible to implement the functionality using JS, and yes there are workarounds, and I think there even is a lib, but it sure would be very handy to be able to simply write one single line of CSS instead. My implementation in the source of https://tobireif.com/ is more than 50 lines of JS - if people could instead write a single line of CSS then that would save a lot of typing. By the way @litherum : If the implementation is smart enough, perhaps one pass would be sufficient → no loop / double-pass. Perhaps the syntax could look like this:
The sizing/fitting should honour the (potential) padding of the container. |
Using a small number of passes is unlikely to work in the general case, because if we get it wrong, the text will overflow its container and wrap, which would be catastrophic. Any generalized implementation would have to iterate until the algorithm converges. Such an algorithm would be a great way to make a browser hang. |
If you do want to provide this widely requested feature - perhaps you could try it out 😀 If your algorithm is smart regarding calculating the estimated target value, it will not need many passes, and it might need only one or two passes. For all and any cases.
When you try it out, and limit the maximum number of passes to 2 == no browser hang at all, and if your algo can estimate the correct value pretty well, then there's a good chance that the result will be sufficiently good. You'd have to try it out though. If you do not want to provide that feature no matter what, and thus do not want to create a quick "beta" implementation for seeing what's feasible, then there's not much reason to continue the discussion. In that case please close the ticket. I did create a quick implementation using JS and found that it works sufficiently well using only two passes. The code is at https://tobireif.com/ -> source -> "var topLevelHeadings". It's just a quick (but good enough for that case) implementation - I'm 100% sure that you could come up with a much better (and generally applicable) algo 😀 Here's another JS implementation: None of the above implementations causes any noticeable performance issue. And: The latter is a general lib. |
I'd prefer CSS that's based on the parent element width, not on the viewport width. (Because generally the element width might change without the viewport changing.) The feature is a (very popular) wish - the specification of that feature (including all relevant details) would be up to the CSS WG. |
(Oh, and if that feature would be only feasible to spec/implement for a defined set of simple types of cases, I'm sure that simple feature would be widely appreciated as well 😀 The syntax still could be |
If and when there will be an ew unit ("element width", as in EQCSS), and if and when there will be clamp() , then the functionality in this feature wish ticket here could be expressed sufficiently succinct, eg:
|
Where are you getting |
Here's the definition of switch(unit) {
case 'ew':
return tag.offsetWidth / 100 * number + 'px'
case 'eh':
return tag.offsetHeight / 100 * number + 'px'
case 'emin':
return Math.min(tag.offsetWidth, tag.offsetHeight) / 100 * number + 'px'
case 'emax':
return Math.max(tag.offsetWidth, tag.offsetHeight) / 100 * number + 'px'
} I was thinking of isolating just these tests into their own package (and maybe the element query tests from jsincss-element-query) so other plugin builders could more easily re-use the same tests in their plugins. |
Yeah, it'd not be the real deal where the implementation figures out the value required for making the text fit its container. It'd just be a pragmatic way to get the feature with just one line of CSS. (And yes, 30ew means 30% of the element width. The exact number is just an example, it could be eg 45.5ew .) |
(I was replying to @jonjohnjohnson , just so there's no misunderstanding @tomhodgins 😀) |
Ideally we could state in CSS "always fit this word/line of text inside its parent (by auto-adjusting the property "foo" eg font-size or letter-spacing), no matter what font is used". |
We now do have For the desired capability we would need new keywords or functions indeed. |
Yep 😀 |
No one has mentioned the SVG Their algorithm applies to a block, not a line - I expect that the text is progressively adjusted and layout retried until it fit. It's certainly going to be multi-pass and expensive - you can take a guess at a start value easily enough, but word-breaks at the end of the line necessarily make the algorithm iterative to find the best value. Doing it once for print layout is one thing, but it would be horrendous if you were resizing a window with this on. We've been asked for similar functionality a few times over the years, but I believe only ever for "fit to line" rather than "fit to block". I think it's more of an issue in print, at least until they start selling paper with a horizontal scrollbar. If you restricted it to just scaling either |
@faceless2 wrote:
That would be sensible (with |
I’ve seen cases where this has been applied to each word, for some definition of word. Nonetheless, I guess it would be fine to do this by fitting the whole textual box content on a single line. (An |
Hi all, I'd like to revive the conversation and provide another perspective on the utility of supporting a feature like this in CSS. There are many designs that leverage careful placement and styling of text. A lot of time is spent by designers and engineers to implement these designs, but often only just in English. As soon as the text gets translated to another language, especially if the translation is much longer or shorter, applying the same CSS to the text that worked for English often causes issues such as text overflowing, truncating, breaking mid-word, widows, etc. As a result, this feature would make it easier to localize text while preserving design intent.
There are several JS libraries that attempt to implement this resizing. However, one limitation of a JS implementation is that it causes layout shifts for server-side rendered (SSR) pages. Since the server does not reliably know the dimensions of the client's device, the text needs to wait for the page to be hydrated before resizing. If supported in CSS, text would be able to render at just the right size even on initial render of SSR'ed pages. In addition, while performance is certainly a consideration, other expensive CSS features such as animating height also exist and the performance implications are well known. Given the benefits of a "FitText" feature, it would be nice to be able to support this and allow developers weigh the performance cost against the benefits for their use case. |
Noting that WCAG is referenced by legislation ... so not just a naive case of "let's tweak WCAG then" Also: a user wants to make text bigger. That's their prerogative. Coming along (as an author) saying "actually, I'd argue that no, that's not what you want" is ... maybe not the right approach.
You don't know what browser window/viewport size the user started at, so ... you don't know when the fit-to-width kicked in. |
Years pass, legislation changes. We're trying to design the language for the future. If the current specified criterion is absurd, it needs to be changed. Once it changes, and legislation catches up, the feature will stop violating it. Yes, those who are required by law to follow WCAG could not use the feature now, but could in N years from now on.
As someone who uses various methods of zooming text and content of pages every single day, I never want to “make text bigger”. I want to access content by increasing the size of small texts, usually paragraphs. This feature will not change anything in how minimum font-size works on pages, it will only allow authors to increase the size of certain elements to be conditionally larger than they would be without it. At a smaller viewport, a header fully fitting into available space from the get-go, will be rendered at 20px size, and could be without issue increased in size to 40px via browser zoom. On larger viewports, the same header will be rendered at an already larger size. |
While not trying to invalidate your perspective, note that that's what it is ... your take. Low vision users may have a different need than you. I'd suggest consulting with these groups (such as the https://www.w3.org/WAI/about/groups/task-forces/low-vision-a11y-tf/ once it restarts) rather than just assuming that of course all users will be the same / have the same preference. |
In addition to the previous comment, that feels very presumptive about how authors might use a feature like this. There's no guarantees that this will only be used on headers, or only with text that is already above a minimum size, or only within containers that are already large and will grow in size, and we shouldn't assume they will. |
I just finished a research project on personalization and accessibility (under review) and the most common action taken by people who are considered low vision is to customize text size. Inability to change text size is a pretty significant barrier for many people. Meta-analysis research from 2020 estimates that around 600 million people worldwide would be considered on the spectrum of "low vision" to blind, which was roughly 8% of the world population in 2020. These numbers are expected to grow, due to compounding socio-economic factors, by 2050. This isn't just a small slice of people. |
Is there a way for the site visitor to specify they want to increase the height of the container rather than shrinking the font? |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
I'll need to do more research on this topic before I could respond further, but it feels necessary to link up two related issues with discussions from WCAG/WCAG3 here:
On the first reading, the discussions there mostly agree that SC 1.4.4 is not ideal, both in ensuring the small text is readable (where you could want to bump it up more than 200%), and that for larger texts the percentage (if used at all) should be smaller, as otherwise headers could fail SC 1.4.10. There were no resolution about anything though, and I will keep an eye on the Low Vision task force, and will bring these issues, and how they apply to this feature to them once it is restarted. Thank you, @patrickhlauke, for pointing to this group. @tobireif Yes, GH is the place to discuss that, although maybe we should open a separate issue about the possible accessibility implications of this feature :) |
That would be nice of you. |
There are now over 50 comments below my feature wish #2528 (comment). That's awesome, but it's getting a bit much 😁 Here's the new place to discuss related topics: #12038 |
Making text dependent on the viewport has always been problematic for accessibility, this is well documented. This is why we usually advise not to use clamp or vh/vw units in font sizes. It just overrides user preferences unnecessarily. The only way this could pass muster is to require browsers to include an opt-out to the behavior. Or to ignore it when users zoom in, which would defeat the purpose of the proposal. I second Patrick’s pointer at LVTF and general W3C horizontal review. It might be good to generally outline when you get specific accessibility input to ensure that proposals are feasible to implement so that all users can use them. |
Re-tagging (as resolution was Start work on this in Fonts 5) |
Am I correct that the accessibility problem here only arises if the container width is tied to viewport width in some way? If the container width is a simple length like 500px then you could use zoom to enlarge fit-to-width text. I’m not sure I’m ready to agree that an opt-out or disabling-on-zoom is the only way to make this work. Given that quite a lot of current font-size usage has some vw component added in, I wonder if there is something (in the specs, in zoom behavior, in authoring advice, or something else I have not thought of) we can do to make the general problem better that would also help this fit-to-width case. |
The way to solve the fit-to-width issue with font-size I am currently thinking about: make the “max font-size” limit to be 200% of the starting original font-size. With all major browsers that I tested, they provide around 500% full-page zoom (not counting pinch-to-zoom and similar cases). That means that if we limit the max font-size that our fit-to-width algorithm could reach to 200%, the built-in zoom allows a user to zoom the original text to around 250% in the worst scenario. This will be very similar to the case described in the “Understanding SC 1.4.4” with the size of the layout (see second note there). This will also solve another issue that I encountered with fit-to-width much more often than an inability to zoom in — an ability to zoom out. An unbounded fit-to-width on bigger screens can lead to text that is too big, it becomes unreadable. I am planning to research the existing cases for fit-to-width, and see if 200% max font-size will be enough for them. I anticipate that it should — and not having this big range of values will also mean that authors will have to define a better fallback size for browsers that won't support fit-to-width. |
@astearns speaking of "quite a lot of current font-size usage has some vw component", note https://www.w3.org/WAI/WCAG21/Techniques/failures/F94 |
@patrickhlauke yes, it’s absolutely a failure (for accessibility and for design generally) to use viewport units as the only component in sizing text. Current usage as I understand it has vw as a small extra component (like |
Um, couldn't this all perhaps be a bit easier? I always thought of this feature like this: You have for example the usual stage-filling banner at the top of the page with a large headline. You are using e.g. a CMS and the text is variable (perhaps even translated to different languages). You want to make that headline as large as possible. Up until now, I would be quite conservative and use like 24px, because I don't know how long that headline might be for all pages. In most cases though, the headline could be larger. So, the font-size: 24px is basically a lower bound. In the future, I could say: font-size: 24px-or-more. That would make the headline as large as possible before it needs to wrap around. In ideal world, I could even specify a number of lines or a height - not only fit to a single line. Now, the first important thing here is, that the headline only gets larger. I don't see an accessibility problem there. Next, the calculation should IMHO be done as if the zoom level was at 100%. If the result of this calculation in a specific case is e.g. that 48px would be the maximum until the headline wraps around (or consumes more than the given number of lines), then the factor would be 2.0. Now if I zoom to 200%, the font-size should be 96px - even if more lines are created. This way, the zoom level would still take full effect and we wouldn't have that problem with accessibility. It's the same as if I specified 48px just for this page right away. Hope it makes sense. Just my 0.02€... |
I'm not Pat, but jumping in here because I have been begging authors not to use viewport units, It's also my experience that approach doesn't satisfy what many authors want by folding in viewport units. And so that's not how I see authors use viewport units in the wild (or developer blogs and sites). So I am only jumping in to this thread to ask that we don't dismiss the risk of viewport units by framing some of their uses as "small tweaks" without better defining what that means. |
Thanks @aardrian. To be clear I’m not looking for an excuse to dismiss the problem. I’m looking for the boundaries of the problem so that if and when we have a proposal on how to address it, we’ll know how to evaluate whether the proposal is an actual solution. |
Yeah, sorry @astearns, I did not think you looking for an excuse and it was not my intent to convey that. Mostly I wanted to make sure I could point to my own comment when someone said, "but the Anyway, I think one boundary is when a viewport unit is used for anything other than additive values. |
For those not watching Blink intents: Intent to Prototype: CSS fit-width text I’ve asked them in their intent to prototype to acknowledge and work through the accessibility concerns raised here. |
Thanks, Alan. So far there is only a single mention in passing:
|
and this is where i see a dangerous slippery slope sometimes. things get prototyped, some developers already start using it...next thing you know it's a fait-accompli |
not sure how "minimum font setting" (assuming this means "having a minimum font size defined in settings") would help here, unless i'm missing something |
@patrickhlauke Note that “prototype” currently means only in Canary under a feature flag (and, I think, recently, under a CLI feature flag), so it should not go anywhere near developers for now. It is only “intents to ship” that are dangerous and should not happen fast, but prototypes allow us to test our assumptions about the behavior, and iterate on them, including pursuing potential fixes to the issues we know of (and to identify new issues). Re: what could help — could you give your opinion on #2528 (comment)? |
This thread shows that it's a widely required feature:
https://twitter.com/sindresorhus/status/979363460411609091
Example of a workaround: Open https://tobireif.com/ and (eg using dev tools responsive mode) resize the page down to 250px width while watching the text "Welcome".
The text was updated successfully, but these errors were encountered: