Fit text within a button

Column[Table[
Button["ABCDEFGHIJKLMNOPQRS", Null,
ImageSize -> i], {i, {50, 100, 150, 200}}]]


will output

As in the above example, Mathematica put all the text into a button,
even if the height of a button is increased.

When creating a button, if the text is too long, is it possible to display only the front part of the text?
Below is an imaginary code, and the pic was created by photoshop.

To put my question differently, I want to start with the width and height of the button fixed first.

The following should work well for ordinary text, without any magic numbers or rasterization tricks required:

Column[
Table[Button[
Pane["ABCDEFGHIJKLMNOPQRS",
{
Full,
Dynamic[CurrentValue@"FontLineHeight"*# + #2 & @@ CurrentValue@LineSpacing]
},
BaselinePosition -> Baseline,
Alignment -> {Center, Automatic}
],
Null, ImageSize -> i
], {i, {50, 100, 150, 200}}]]


This basically relies on Pane to do the clipping in both directions for us. For the width, we inherit the size from the Button using Full, while we try to predict the height of a line of text using CurrentValue values for "FontLineHeight" and LineSpacing.

This even works nicely for dynamically sized buttons:

Pane[Button[
Pane["ABCDEFGHIJKLMNOPQRS", {Full,
Dynamic[CurrentValue@"FontLineHeight"*# + #2 & @@
CurrentValue@LineSpacing]},
BaselinePosition -> Baseline,
Alignment -> {Center, Automatic}
],
Null
], AppearanceElements -> "ResizeArea"]


• Thank you, the second solutions maybe the ultimate solution! Aug 7 at 11:20
• Which Mathematica version do you use? Here is what I get with version 13.1.0 on Windows 10 x64: screenshot. Also, With seems to be redundant in your code. Aug 7 at 13:56
• Your code can be fixed by replacing Alignment -> Center with Alignment -> {Center, Automatic}. Aug 7 at 14:09
• @AlexeyPopkov Thanks for the fix! I should really get into the habit of opening 13.1 instead of 12.3.... As for the With: Yes, that is indeed an unnecessary remnant from a previous attempt Aug 7 at 14:28
• BTW, may be you know a way to get absolute current value for Full (for this question)? Aug 7 at 14:31

First, define an auxiliary function:

imageSize[expr_] :=
Differences[Rasterize[Annotation[expr, "expr", "Region"], "Regions"][[1, 2]]][[1]]


Now

expr = "ABCDEFGHIJKLMNOPQRS";

{width, height} = imageSize[Style[Pane@expr, "GenericButton"]]

Column[Table[Button[Pane[expr, ImageSize -> {Min[i - 6, width], height},
Alignment -> {Center, Automatic}, BaselinePosition -> Bottom],
Null, ImageSize -> i, Alignment -> Center], {i, {50, 100, 150, 200}}]]

{104., 13.}


I do not know how to do it with text and if it is possible (unless you are willing to change the font size).

But you can do it by converting the text to an image, then use ImageTake. Here is the result

text = Rasterize["ABCDEFGHIJKLMNOPQRS"];
{row, col} = ImageDimensions[text];
fix[i_, width_] := If[i < width, ImageTake[text, {All}, {1, i}], text]
imageSizes = {30, 50, 100, 150, 200};
Column[Table[Button[fix[i, row],Null,ImageSize->i, Alignment-> Left], {i,imageSizes}]]


The above is not perfect, it would be better to keep the text as text ofcourse as it would be more clear.

Another option is to do the following,

Using

text = "ABCDEFGHIJKLMNOPQRS";
n = StringLength[text]
imageSizes = {30, 50, 100, 150, 200};
fix[text_String, imageSize_, maxSize_, numberOfLetters_] :=
If[imageSize/maxSize < 1,
StringTake[text, Round[imageSize/maxSize*numberOfLetters]], text]

Column[Table[
Button[fix[text, i, Max[imageSizes], n], Null, ImageSize -> i,
Alignment -> Left], {i, imageSizes}]]


The above uses the largest size, which is 200, and obtain the number of letters to use based on the ratio with the total number of letters in the string and the current image size. So when the current size is 200, all the letters will be used.

ps. you could always add ... if you want for the cases when truncation happen.

You can also use Short[].

Column[Table[
Button[Short["ABCDEFGHIJKLMNOPQRS", i], Null,
ImageSize -> Automatic], {i, {0.05, 0.07, 0.1, 0.2}}]]