pre
-posterous Mobile BrowsersI was alerted to the fact that code on my home page looked teensy-tiny on Android. What could be wrong? It was just enclosed in pre
tags. Preposterously, and probably for prehistoric reasons, mobile browsers apply weird rules to preformatted code instead of just following CSS styles. It took me foreever to find the magic pixie dust, so I wrote it up so that the search- and chatbots can find it.
My home page has a sequence of code snippets that shows the evolution of number formatting through the ages. Each snippet is simply enclosed in <pre>...</pre>
. What could possibly go wrong?
You can no longer see the effect on my home page because I fixed it, as explained below. But check out this test page on your mobile device.
Here is how it looks like with Chrome on Android (click to magnify):
Firefox on Android displays the test page in essentially the same way.
I tried searching for “tiny pre font android”, and to my surprise it was slim pickings.
monospace, monospace
hack. If you declare
font-family: monospace, monospace;then browsers will stop reducing the font size for monospace fonts. Go figure.
monospace, monospace
no longer holds for “most Android browsers”. One answer suggests to add "Courier"
or "Courier New"
or both to the font stack. In my own testing, that didn't make any difference.<pre>
text. Exactly my problem. One suggestion is to use a CSS media query to scale the pre
font size on “narrow screens”. But what if the user rotates to landscape or has a tablet? Another answer suggests to use
<meta name="viewport" content="width=device-width, initial-scale=1">That is generally a good idea. It stops the mobile browser from laying out the page on a virtual window and then shrinking it. And it stops the browser from using a teensy tiny font for
pre
. I don't love that the change must be made in HTML instead of CSS.pre { white-space: pre-wrap !important; }Huh? Why should
white-space
have anything to do with font sizing? But amazingly it works. Even without the !important
.I asked ChatGPT: “When viewing a web page on my Android phone, code in pre tags comes out tiny. How should one fix the web page so that the code has the same size as the surrounding text?” Its answer:
One way to fix the issue with the code in pre tags appearing tiny on an Android phone is to apply CSS styling to the pre tag. Here is an example CSS rule that can be added to the page's CSS file:
pre { font-size: inherit; line-height: 1.5em; white-space: pre-wrap; }
I should have tried the chatbot first instead of using a search engine! I asked a followup question: “Why does this work? white-space should have nothing to do with font size!” The reply:
You are correct that the
white-space
property is not directly related to font size. However, in this case, setting thewhite-space
property topre-wrap
actually helps to prevent the code from overflowing the container and causing it to appear smaller.By default, the
white-space
property of thepre
tag is set topre
, which means that whitespace in the code will be preserved and the text will not wrap. This can cause the code to overflow the container if it is too wide, which can make it appear smaller and harder to read.Setting the
white-space
property topre-wrap
allows the text to wrap when it reaches the end of the container, which helps to prevent the code from overflowing and appearing smaller. This property also preserves the formatting of the code, so the indentation and line breaks will be maintained.
This is a weird argument. Why is overflowing code smaller and harder to read when it doesn't wrap?
Anyway, the solution works. Fortunately, wrapping is only a visual feature. When you copy the code from the page, there are no added line breaks.
You can also set white-space
to break-spaces
, which is almost the same, but it wraps trailing spaces. I don't think that's useful.
I don't love giving up the overflow behavior for pre
. I prefer for readers to scroll instead of pondering whether something got wrapped.
I used the Firefox Remote Debugging tool to inspect the font size of the pre
areas. Here are the reports:
Style | Reported font size |
---|---|
None | 12px |
white-space: pre-wrap |
12px |
white-space: break-spaces |
12px |
white-space: pre |
12px |
font-family: monospace, monospace |
16px |
font-size: 1em |
1em |
What are the dev tools smoking? The first four code blocks do not all have the same size!
My guess is that there are two unrelated issues. First, many monospace fonts have a taller x-height than text fonts. Since the mist of time, browsers use different font sizes for text and monospace fonts. On desktop browsers, the user can override the browser defaults. Since they can't do that on mobile browsers, your best bet is to use matching custom fonts for text and code. Or use the monospace, monospace
hack and hope for the best.
The tiny pre
is a separate, and more frustrating problem. I can't begin to understand why anyone ever thought it was a good idea to render pre
content at about 50% of the text size on mobile browsers. But someone must have had a reason for it. And apparently the behavior is kept for compatibility unless the browser sees some sign of modernity. Such as the viewport
meta tag or the white-space
CSS property.
Finally, I ran into Rahul Chhodde's article Improving mobile design with the latest CSS viewport units, which casually suggested to use:
body { font-size: 3vmax }
I tried that (with 2vmax
) in this document. On the desktop, the page scales when you resize the window. (This is often called “fluid typography”.) On mobile, you get a reasonable font size in portrait and landscape orientation. Without using pre-wrap
, the pre
elements are a little smaller than they should be according to the CSS, but they are readable. I have no explanation for this.
pre
contents to be teensy tiny on mobile browsers. Set the white-space
CSS property if you are ok with wrapping. Consider the viewport
meta tag. Or try fluid typography.
Comments powered by Talkyard.