A place to cache linked articles (think custom and personal wayback machine)
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

index.html 39KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692
  1. <!doctype html><!-- This is a valid HTML5 document. -->
  2. <!-- Screen readers, SEO, extensions and so on. -->
  3. <html lang="fr">
  4. <!-- Has to be within the first 1024 bytes, hence before the <title>
  5. See: https://www.w3.org/TR/2012/CR-html5-20121217/document-metadata.html#charset -->
  6. <meta charset="utf-8">
  7. <!-- Why no `X-UA-Compatible` meta: https://stackoverflow.com/a/6771584 -->
  8. <!-- The viewport meta is quite crowded and we are responsible for that.
  9. See: https://codepen.io/tigt/post/meta-viewport-for-2015 -->
  10. <meta name="viewport" content="width=device-width,initial-scale=1">
  11. <!-- Required to make a valid HTML5 document. -->
  12. <title>Time to upgrade your monitor (archive) — David Larlet</title>
  13. <meta name="description" content="Publication mise en cache pour en conserver une trace.">
  14. <!-- That good ol' feed, subscribe :). -->
  15. <link rel="alternate" type="application/atom+xml" title="Feed" href="/david/log/">
  16. <!-- Generated from https://realfavicongenerator.net/ such a mess. -->
  17. <link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons2/apple-touch-icon.png">
  18. <link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons2/favicon-32x32.png">
  19. <link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons2/favicon-16x16.png">
  20. <link rel="manifest" href="/static/david/icons2/site.webmanifest">
  21. <link rel="mask-icon" href="/static/david/icons2/safari-pinned-tab.svg" color="#07486c">
  22. <link rel="shortcut icon" href="/static/david/icons2/favicon.ico">
  23. <meta name="msapplication-TileColor" content="#f0f0ea">
  24. <meta name="msapplication-config" content="/static/david/icons2/browserconfig.xml">
  25. <meta name="theme-color" content="#f0f0ea">
  26. <!-- Documented, feel free to shoot an email. -->
  27. <link rel="stylesheet" href="/static/david/css/style_2020-06-19.css">
  28. <!-- See https://www.zachleat.com/web/comprehensive-webfonts/ for the trade-off. -->
  29. <link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
  30. <link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
  31. <link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
  32. <link rel="preload" href="/static/david/css/fonts/triplicate_t3_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
  33. <link rel="preload" href="/static/david/css/fonts/triplicate_t3_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
  34. <link rel="preload" href="/static/david/css/fonts/triplicate_t3_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
  35. <script type="text/javascript">
  36. function toggleTheme(themeName) {
  37. document.documentElement.classList.toggle(
  38. 'forced-dark',
  39. themeName === 'dark'
  40. )
  41. document.documentElement.classList.toggle(
  42. 'forced-light',
  43. themeName === 'light'
  44. )
  45. }
  46. const selectedTheme = localStorage.getItem('theme')
  47. if (selectedTheme !== 'undefined') {
  48. toggleTheme(selectedTheme)
  49. }
  50. </script>
  51. <meta name="robots" content="noindex, nofollow">
  52. <meta content="origin-when-cross-origin" name="referrer">
  53. <!-- Canonical URL for SEO purposes -->
  54. <link rel="canonical" href="https://tonsky.me/blog/monitors/">
  55. <body class="remarkdown h1-underline h2-underline h3-underline hr-center ul-star pre-tick">
  56. <article>
  57. <header>
  58. <h1>Time to upgrade your monitor</h1>
  59. </header>
  60. <nav>
  61. <p class="center">
  62. <a href="/david/" title="Aller à l’accueil">🏠</a> •
  63. <a href="https://tonsky.me/blog/monitors/" title="Lien vers le contenu original">Source originale</a>
  64. </p>
  65. </nav>
  66. <hr>
  67. <main>
  68. <figure class="cover">
  69. <img src="https://tonsky.me/blog/monitors/cover.gif"/>
  70. Illustration by <a href="https://www.behance.net/yuliaprokopova" target="_blank">Yulia Prokopova</a>
  71. </figure>
  72. <p>I am a programmer. I do not deal with digital painting, photo processing, video editing. I don’t really care for wide gamut or even proper color reproduction. I spend most of my days in a text browser, text editor and text terminal, looking at barely moving letters.</p>
  73. <p>So I optimize my setup to showing really, really good letters. A good monitor is essential for that. Not nice to have. A MUST. And in “good” I mean, as good as you can get. These are my thoughts, based on my own experience, on what monitors work best for programming.</p>
  74. <h1 id="low-density-displays">Low-density displays</h1>
  75. <p>According to <a href="https://twitter.com/nikitonsky/status/1260287480638701568">my research among programmers</a>, 43% are still using monitors with pixel per inch density less than 150:</p>
  76. <figure>
  77. <img src="https://tonsky.me/blog/monitors/research.png"/>
  78. </figure>
  79. <p>Why is this a problem? Because the only way to get good letters is by spending more pixels per letter. That simple. In the past, the displays’ pixel count was small, so we learned to live with that and even invented some very clever tricks to make our lives better. The two important things to understand are:</p>
  80. <ul>
  81. <li>Times of low-resolution displays are over. High-resolution displays are a commodity now.</li>
  82. <li>Tricks developed for low-resolution displays didn’t magically make text look good. That always was and still is impossible. They just made text slightly less terrible, but it still is terrible.</li>
  83. </ul>
  84. <p>If you think that you can somehow make your 1080p display render good text, that it just needs a few more tweaks, NO. This won’t happen. The sooner you accept that the sooner you can start looking for real solutions.</p>
  85. <p>To make my claim better founded, let’s look in detail how text <em>really</em> looks on a low-resolution display and what can be done about it (spoiler: not much!).</p>
  86. <h2 id="not-enough-pixels">Not enough pixels</h2>
  87. <p>First, there are simply not enough pixels to draw a letter. Let’s take Consolas, a font that was developed specifically for programmers. Microsoft worked really hard to fine-tune it for low-resolution rendering. We set it at 14px, which is default in VS Code (and people often go lower than that!):</p>
  88. <figure>
  89. <img src="https://tonsky.me/blog/monitors/consolas_gray_1x.png"/>
  90. Consolas at 14px, macOS
  91. </figure>
  92. <p>On that size, capital letter B takes up mere 6×9 pixels on a screen. Lowercase letters only have 7 (seven!) vertical pixels to work with. That’s NOT MUCH. I have more fingers than that. No matter how good font is designed, it’s hard to show anything when all you have is seven pixels. Anything slightly more complex than “T” or “H” becomes an illegible pixel mess.</p>
  93. <p>Look at the “g” in the picture above. It’s hard to say where strokes start or end, or even how many of them are there. It’s just random gray noise or a checkerboard, but not a letter. This is a letter:</p>
  94. <figure>
  95. <img src="https://tonsky.me/blog/monitors/consolas_24x.png"/>
  96. Consolas at 168px
  97. </figure>
  98. <p>It’s a shame, really, watching these beautiful fine details getting clamped into mere 7×10 pixels.</p>
  99. <h2 id="the-dreadful-hinting">The dreadful hinting</h2>
  100. <p>To fight the problem of everything being a gray mess, Windows uses pretty aggressive hinting. Basically, it just bends and moves letter strokes to the nearest pixel, ensuring more crisp boundaries.</p>
  101. <p>And it works! Fonts do look better with hinting than without it:</p>
  102. <figure>
  103. <img src="https://tonsky.me/blog/monitors/hinting.png"/>
  104. No hinting (macOS) → Hinting (Windows)
  105. </figure>
  106. <p>Don’t get your hopes up though: it’s still a mess. It doesn’t make text look <em>good</em>. It makes it look <em>better</em>, but it is still bad.</p>
  107. <p>The main problem with hinting, though, is that it destroys letter shapes. Pixels are rendered not where they are supposed to be, but rather where pixel grid happens. To give you a taste:</p>
  108. <figure>
  109. <img src="https://tonsky.me/blog/monitors/ttf_hinting.png"/>
  110. Verdana (k) and Times New Roman Italic (z) before rasterization at 13px. <a href="http://web.archive.org/web/20160304021305/http://antigrain.com/research/font_rasterization/index.html">Source</a>
  111. </figure>
  112. <p>The idea is that it’ll look better when rendered to the actual pixels.</p>
  113. <p>But even if we just look at vertical hinting of horizontal stems, it’s still changes font way too much:</p>
  114. <figure>
  115. <img src="https://tonsky.me/blog/monitors/hinting_align.png"/>
  116. </figure>
  117. <p>See how horizontal stems are offset from their actual position in the vector font file? The error here is as big as ¼ pixel!</p>
  118. <p>But hey! If you never saw a high-res Consolas, who cares if <code class="language-plaintext highlighter-rouge">g</code> is the same shape or not? Who cares if stems are in the wrong place if you don’t know where they should’ve been in the first place? Well, sometimes problems are more obvious: circles are not circles, equal distances become not equal, proportions are all wrong, what supposed to be small becomes huge and vice versa, etc. Here:</p>
  119. <figure>
  120. <img src="https://tonsky.me/blog/monitors/hinting_numbersign.png"/>
  121. </figure>
  122. <p>After moving horizontal stems to match pixel grid (by offsetting them up to ½ pixel!), Windows is having a hard time splitting 7 other pixels into three equal gaps. Unfortunately, alternative is no better:</p>
  123. <figure>
  124. <img src="https://tonsky.me/blog/monitors/no_hinting_numbersign.png"/>
  125. </figure>
  126. <p>From my personal experience <a href="https://github.com/tonsky/FiraCode/issues?q=is%3Aissue+is%3Aopen+label%3Ahinting">building Fira Code</a>, I’ve seen too many ways simple idea “just stick edges to the nearest pixel” can go wrong:</p>
  127. <figure>
  128. <img src="https://tonsky.me/blog/monitors/hinting_failures.png"/>
  129. </figure>
  130. <figure>
  131. <img src="https://tonsky.me/blog/monitors/hinting_failures_2.png"/>
  132. </figure>
  133. <p>This is a game that just can’t be won.</p>
  134. <h2 id="a-fractional-pixel">A fractional pixel</h2>
  135. <p>Can you draw a perfect line that is thinner than one pixel?</p>
  136. <p>Yes. The idea is simple, really. Your display’s pixel consists of three vertical subpixels, each responsible for their color. We can light them up individually, effectively tripling horizontal resolution!</p>
  137. <figure>
  138. <img src="https://tonsky.me/blog/monitors/subpixel_1.png"/>
  139. </figure>
  140. <p>In practice, though, you can’t implement it literally like that, because you’ll just end up with a christmas light mess:</p>
  141. <figure>
  142. <img src="https://tonsky.me/blog/monitors/subpixel_2.png"/>
  143. </figure>
  144. <p>So you have to compromise again (inside another compromise!), putting limit of how far can color deviate from black:</p>
  145. <figure>
  146. <img src="https://tonsky.me/blog/monitors/subpixel_3.png"/>
  147. </figure>
  148. <p>Which means letter shapes are not 3× sharper, they are maybe 1.5× sharper, but overall still pretty blurry.</p>
  149. <figure>
  150. <img src="https://tonsky.me/blog/monitors/subpixel_4.png"/>
  151. </figure>
  152. <p>In the end, there is an improvement in readability, but at the same time, black-on-white text gets a slight teal-and-orange halo around it. It’s not super bad, but you <em>can</em> see it.</p>
  153. <p>What I am trying to say is: all these tricks work. Having them is strictly better than not having them. For low-DPI displays all those are <em>a must</em>. But at the same time, they are a tight compromise made in times where we didn’t have better displays. Now that we have them, it’s time for all those tricks to go.</p>
  154. <figure>
  155. <img src="https://tonsky.me/blog/monitors/subpixel_5.png"/>
  156. Consolas 14px with ClearType and hinting → Consolas 14px @2x
  157. </figure>
  158. <h1 id="retina-macbooks">Retina Macbooks</h1>
  159. <p>Retina Macbooks <em>can</em> make text look good. However, there are two things you absolutely must do.</p>
  160. <h2 id="turn-off-font-smoothing">Turn off font smoothing</h2>
  161. <p>First, turn OFF “Font smoothing” in System Preferences → General:</p>
  162. <figure>
  163. <img src="https://tonsky.me/blog/monitors/no_smoothing.png"/>
  164. </figure>
  165. <p>I’m not sure what the default value for it is these days, but make sure it’s OFF anyways.</p>
  166. <p>UPD: Based on the feedback, seems that default value for it is ON. Be sure to switch it OFF!</p>
  167. <p>That preference name is misleading. It used to be called “LCD font smoothing”, which suggested subpixel antialiasing. But Apple removed subpixel antialiasing from macOS in 2018, the same month it retired its last non-retina notebook.</p>
  168. <p>The other thing the name suggests is that your fonts might not be smoothed at all. This is not the case either.</p>
  169. <p>What it actually does is it makes font slightly bolder:</p>
  170. <figure>
  171. <img class="hoverable" src="https://tonsky.me/blog/monitors/smoothing_anim.png"/>
  172. Hover over or click the image to see the difference
  173. </figure>
  174. <p>So, why would you want it off? Because there’s no automated way to make font bolder. Normally each font weight is carefully designed by a professional type designer. It’s a tricky process that involves millions of constraints. If you try to simulate it by, for example, adding an outline to the letter, it will look terrible:</p>
  175. <figure>
  176. <img class="hoverable" src="https://tonsky.me/blog/monitors/fake_bold.png"/>
  177. Real bold v. Fake bold simulated with an outline. Hover or click to see the outline
  178. </figure>
  179. <p>But that’s exactly what “Font smoothing” in macOS does! Here’s another example. MacOS blurs pixel-perfect boundaries with “font smoothing”:</p>
  180. <figure>
  181. <img src="https://tonsky.me/blog/monitors/smoothing_artefacts.png"/>
  182. </figure>
  183. <p>Imagine a font designer who carefully balanced every letter, placed each point down to 1/100 of the pixel, only to be ignored by dumb software that thinks it knows better.</p>
  184. <p>What does that mean for us, programmers? If you take a font that was hand-optimized for particular pixel size (which many programming fonts are, e.g. <a href="https://input.fontbureau.com/info/">Input at 11px</a> or <a href="https://larsenwork.com/monoid/">Monoid at 12px</a>), it will be rendered blurry despite all the efforts.</p>
  185. <figure>
  186. <img src="https://tonsky.me/blog/monitors/smoothing_input.png"/>
  187. </figure>
  188. <p>And all the other fonts, including system ones, will be slightly more blurry than they need to be.</p>
  189. <p>UPD: Chris Morgan <a href="https://news.ycombinator.com/item?id=23553486">mentioned in a comment</a> that this setting might explain why so many designers put <code class="language-plaintext highlighter-rouge">font-weight: 300</code> <a href="https://grumpy.website/post/0PPp8l_pu">as their default web page font</a>. They are over-compensating for font emboldement of macOS!</p>
  190. <h2 id="integer-scaling">Integer scaling</h2>
  191. <p>When I bought my first (and world’s first) Retina Macbook Pro in 2012, it was exactly what was advertised: 2× scaling, every logical pixel rendered to 2×2 screen ones. 2880×1800 screen would be rendered from 1440×900 logical source.</p>
  192. <p>Sadly, reason has left Apple since, and at some point, Macbooks started to get weird non-integer scaling as default. E.g. 2880×1800 screen would have 1680×1050 logical resolution. That is 1.7142857143… scaling factor, or 12/7.</p>
  193. <p>Why? I guess, someone at Apple decided that more screen real estate sells better. The problem is, it’s not that big an increase: just a mere 15%. I mean, 15% is good, but not game-changing. The terrible part is, it comes at the cost of losing any chance to render ANY pixel-crisp image at all!</p>
  194. <p>Let’s see. 12/7 scaling factor means that for every 7 logical pixels there are 12 corresponding screen pixels. Meaning, every 7 pixels you have a chance to draw a 7-pixel tall rectangle and that’s your only chance to align with the pixel grid.</p>
  195. <figure>
  196. <img src="https://tonsky.me/blog/monitors/12by7_grid.png"/>
  197. </figure>
  198. <p>Move 1 pixel up or down—you lose. Make it 1px taller or shorter—you lose.</p>
  199. <figure>
  200. <img src="https://tonsky.me/blog/monitors/12by7_grid_offset.png"/>
  201. </figure>
  202. <p>A pixel-perfect line? Too bad you can’t specify 7/12 of a pixel as the line width. Even worse, each 1px line looks differently depending on its vertical position:</p>
  203. <figure>
  204. <img src="https://tonsky.me/blog/monitors/12by7_lines.png"/>
  205. </figure>
  206. <p>It shouldn’t come as a surprise that modern icons are mostly made out of single-pixel-wide strokes:</p>
  207. <figure>
  208. <img src="https://tonsky.me/blog/monitors/12by7_ui.png"/>
  209. Top: 2× scale, bottom: same after 12/7 downscaling
  210. </figure>
  211. <p>It’s hard to imagine someone who wants to look at <em>that</em> on purpose.</p>
  212. <p>(no idea why bottom right pixel is missing on all the icons)</p>
  213. <p>What happens with the text? Nothing good. First it is rendered pixel-crisp at 2× resolution, then downscaled at 85.7142857143…% to fit into physical pixels:</p>
  214. <figure>
  215. <img src="https://tonsky.me/blog/monitors/12by7_text.png"/>
  216. Monoid at 12px. Top: 2× scale, bottom: same after 12/7 downscaling
  217. </figure>
  218. <p>That’s right, UI isn’t even rendered in that weird target resolution. Every Mac app thinks it is rendering at 2×, and only after that OS scales it down to the target resolution. There’s a lot of precision and nuance lost due to this two-step resize process.</p>
  219. <p>In my opinion, nothing can do more harm to the look of UI than this. Even old low-dpi UIs are better since their lines at least align with pixels!</p>
  220. <p>And don’t forget: this is the default. Every Macbook is shipped with these settings. Millions of people are working not knowing they were robbed of the joy of the retina screen.</p>
  221. <p>Luckily for us, this is easy to fix (at least for now). Go to System Preferences → Displays, uncheck Default and select 2× resolution instead:</p>
  222. <figure><img src="https://tonsky.me/blog/monitors/scaling.png"/></figure>
  223. <p>This will make everything on the screen slightly bigger, leaving you (slightly!) less screen estate. This is expected. My opinion is, a notebook is a constrained environment by definition. Extra 15% won’t magically turn it into a huge comfortable desktop. But at least you can enjoy that gorgeous screen and pixel-crisp fonts. Otherwise, why would you buy a retina screen at all?</p>
  224. <h2 id="cleartype-on-windows">ClearType on Windows</h2>
  225. <p>With all this talk about downsides of ClearType and how it’s only a must on low-density displays, should you turn it off on 4k display? In theory, yes. In practice, no.</p>
  226. <p>First of all, Windows doesn’t even have a UI to turn it off. I mean, there’s this checkbox:</p>
  227. <figure>
  228. <img src="https://tonsky.me/blog/monitors/windows_cleartype.png"/>
  229. </figure>
  230. <p>but even if you turn it off, you’ll have to go through configuring ClearType anyway. There’s just no OK button ¯\_(ツ)_/¯.</p>
  231. <p>If you turn it off this way, it’ll disappear in some places, but keep appearing in others. I guess those places use different APIs and one respects this setting while other does not.</p>
  232. <figure>
  233. <img src="https://tonsky.me/blog/monitors/windows_cleartype_mix.png"/>
  234. </figure>
  235. <p>And most importantly, text without ClearType looks like shit. It doesn’t have to (it looks perfect on macOS, for example), but particularly on Windows it’s unbearable. I guess they don’t even test this as an option:</p>
  236. <figure>
  237. <img src="https://tonsky.me/blog/monitors/windows_no_cleartype.png"/>
  238. </figure>
  239. <p>Just for fun, I retyped all the text labels using the same font, size and color, but on macOS:</p>
  240. <figure>
  241. <img src="https://tonsky.me/blog/monitors/mac_no_cleartype.png"/>
  242. </figure>
  243. <p>But ClearType-d text on Windows still looks good, even on 4k display. It’s just a shame we can’t let ClearType go yet.</p>
  244. <h1 id="get-a-monitor">Get a monitor</h1>
  245. <p>Let me express an opinion. This is my blog, after all. I think that notebooks are not good for development. They are great in mobility and convenience, and this argument might outweigh everything else for some people. I accept that. But still, a desktop monitor + external keyboard are <em>always</em> better than a notebook. There might be other reasons for not buying a monitor, but having one, I hope, no one would argue it’s a superior dev environment.</p>
  246. <p>With this out of the way, the question arises, which monitor should you get? From what we already discussed, two things should be clear:</p>
  247. <ul>
  248. <li>It needs to be at least a 4k monitor. Both 5k and 6k are also great, of course.<sup id="fnref:1"/></li>
  249. <li>You need to use the integer scaling factor.</li>
  250. </ul>
  251. <p>That means, if you have a 4k monitor (3840×2160), and use 2× scaling, you’ll get an equivalent of 1920×1080 logical pixels. So it’s a basic 1080p monitor in terms of how much you can fit, but with much crisper UI and text in everything.</p>
  252. <p>Now, it might be tempting to use, for example, 1.5× scaling. That would give you an equivalent of 2560×1440 logical pixels, which, you might think, is much better. This is not how you should use it! The idea of a 4k monitor is NOT to get more pixels but to get the pixel-perfect, high-density UI rendering. Otherwise, a normal 1440p display would work better. A simple rule to remember: <em>pixel alignment outweighs everything else</em>. 1440p display is better at displaying 1440p content than 2160p display is at it.</p>
  253. <p>It’s also possible to run a 4k display at native 3840×2160 pixels. It depends on the size of the display, of course, but in my experience, even 27” 4k displays are too small to run at 1×. The UI will be too tiny.</p>
  254. <h2 id="the-myth-of-apple-patented-ppi">The myth of Apple-patented PPI</h2>
  255. <p><a href="https://bjango.com/articles/macexternaldisplays/">Some articles</a> suggest that Apple computers should only be used with 220 PPI displays (pixels per inch) because that’s the number Apple itself uses on all the Macbooks and iMacs. Sometimes people go as far as saying displays with different PPI are unusable with macOS.</p>
  256. <p>This is what I think. PPI defines the physical size of the pixel (220 PPI means there are 220 pixels per inch, or 1 pixel is 1/220 inch wide). So Apple ensures that pixels on all its devices have the same size. Does it mean macOS controls have the same physical size? Not anymore, after Apple started applying non-integer scaling by default on Macbooks.</p>
  257. <p>Then, it’s nearly impossible to ensure that <em>perceived</em> size, or how big the user <em>sees</em> the control, is the same because the distance to the display is different. For example, on average my eye-to-screen distance is 33 cm with the notebook, but 68 cm with the monitor. That’s 2× difference!</p>
  258. <figure>
  259. <img src="https://tonsky.me/blog/monitors/distance.png"/>
  260. </figure>
  261. <p>That means that the angular size of the 1/220 Macbook pixel is equivalent to 1/110 monitor pixel. I’m actually having smaller <em>perceived</em> pixels on 4k 27” monitor than I have on 15” Macbook Pro!</p>
  262. <p>Even Apple itself understands that! Their iPhones have higher PPI than Macbooks because they are usually looked at from a closer distance.</p>
  263. <p>To sum things up, I don’t see a problem with 24” 4k displays or even 27” displays. I use both with macOS and love both, never had any problems. Of course, 5k or 6k would be better, but those go in the “nice to have” category. 4k is a must-have, an absolute minimum for anyone working with text.</p>
  264. <h1 id="go-120hz">Go 120 Hz</h1>
  265. <p>The world used to be divided into two camps: high-resolution displays and high-frame-rate displays. The former was good for text, latter for gaming, with no middle ground in between. If you like to play competitive games, buy both (and a large table). Gamers had no use for 4k displays since no reasonable game would run at 4k @ 120Hz, and the creative professionals had no use for 120 Hz in photo/text editing. I was in high-res camp since 2014, of course, and would never trade retina text rendering for barely noticeable refresh rate upgrade.</p>
  266. <figure>
  267. <img src="https://tonsky.me/blog/monitors/camps.png"/>
  268. HP Z27 (4k) v. LG 34GL750-B (120 Hz)
  269. </figure>
  270. <p>Well, the split does not exist anymore. Since not that long ago (yes, I’m too lazy to check) you can have both! You can have a 4k monitor that runs on 120 Hz. In fact, that discovery was the main motivation for this article.</p>
  271. <h2 id="why-120hz">Why 120 Hz?</h2>
  272. <p>If you, like me, work with text, you might think that you have no use for 120 Hz. And you would be right. This falls into a “nice to have” category, but if you are looking for ways to improve your experience, this is a great way to do it.</p>
  273. <p>120 Hz gives you a couple of significant improvements:</p>
  274. <ul>
  275. <li>Animations are smoother, up to the point where they start to appear like a continuous motion instead of a very fast slideshow.</li>
  276. <li>Scrolling is very smooth in particular. Browser, code editing, to name a few.</li>
  277. <li>The whole system feels much more responsive.</li>
  278. <li>You can play games and work on a single display.</li>
  279. </ul>
  280. <p>I can’t show you how 120 Hz feels, of course. But this is what you can do to get the idea: switch to 30 Hz and try to work like that for a while.</p>
  281. <p>You’ll notice that everything is poorly animated, but also way less responsive. This is because the time between monitor updates is now 32 ms instead of 16 ms at 60 Hz. That means that whatever you do (press a button, move a mouse), the closest moment in time computer might start displaying the result might be as far as 32 ms away.</p>
  282. <p>32 ms is a long time and easily perceivable. On 60 Hz, that time is cut in half: the longest you need to wait is just 16 ms. On 120 Hz, this is time is cut in half again: from 16 ms to 8 ms. In absolute numbers, you lose an additional 8 ms, which means going 60 Hz → 120 Hz is about half as impactful as going 30 Hz → 60 Hz. Still, something to go after, in my opinion.</p>
  283. <h2 id="what-to-buy">What to buy?</h2>
  284. <p>There isn’t much choice, really. From what I can find, right now there are only four (yes, four!) 4k 120+ Hz displays on the market! I imagine that’s because demand is not that high, but hey, I’m glad we have at least those!</p>
  285. <p>First one is <a href="https://www.asus.com/us/Monitors/ROG-SWIFT-PG27UQ/">Asus ROG SWIFT PG27UQ</a>:</p>
  286. <figure>
  287. <img src="https://tonsky.me/blog/monitors/asus_pg27uq.png"/>
  288. </figure>
  289. <p>Second one is <a href="https://www.acer.com/ac/en/US/content/predator-series/predatorx27">Acer Predator X27</a>:</p>
  290. <figure>
  291. <img src="https://tonsky.me/blog/monitors/acer_x27.png"/>
  292. </figure>
  293. <p>Third one is <a href="https://www.acer.com/ac/en/US/content/conceptd-model/UM.HC1AA.P02">Acer ConceptD CP7</a>:</p>
  294. <figure>
  295. <img src="https://tonsky.me/blog/monitors/acer_cp7.png"/>
  296. </figure>
  297. <p>All are very nice monitors, I’m sure. But the price is a bit too steep (~$2,000), especially for someone for whom getting 120 Hz is not a question of life and death.</p>
  298. <p>There are few more <a href="https://www.tomshardware.com/reviews/best-4k-gaming-monitors-pc-144hz,6023.html">here</a> with a diagonal size of 55” and more, which would be hard to use on a normal desktop.</p>
  299. <p>Finally, by some unbelievable struck of luck, we actually have ONE reasonably priced, reasonably sized 4k 120 Hz monitor. That’s <a href="https://www.acer.com/ac/en/US/content/model/UM.HX3AA.P02">Acer Nitro XV273K</a>:</p>
  300. <figure>
  301. <img src="https://tonsky.me/blog/monitors/acer_xv3.png"/>
  302. </figure>
  303. <p>And that’s the one that I have.</p>
  304. <h2 id="things-to-look-out-for-windows">Things to look out for (Windows)</h2>
  305. <p>Running 4k at 120 Hz is simple on Windows. Make sure your graphics card has DisplayPort 1.4, use it, that’s it. Seriously, it just works.</p>
  306. <figure>
  307. <img src="https://tonsky.me/blog/monitors/windows.png"/>
  308. </figure>
  309. <h2 id="things-to-look-out-for-macos">Things to look out for (macOS)</h2>
  310. <p>MacOS support sucks. Officially none of the Apple computers support anything beyond 60 Hz, even on normal resolutions:</p>
  311. <figure>
  312. <img src="https://tonsky.me/blog/monitors/macs_compatibility.png"/>
  313. </figure>
  314. <p>So buying this display was the pure leap of faith. This is what I figured:</p>
  315. <ul>
  316. <li>4k @ 120 Hz requires 3840 × 2160 × 3 bpp × 120 Hz × 8 = 24 Gbit/s. Just below of <a href="https://en.wikipedia.org/wiki/DisplayPort#1.3">25.92 Gbit/s of DisplayPort 1.3 / 1.4</a>.</li>
  317. <li>HDMI 2.0 only provides 18.0 Gbit/s, so it has to be DisplayPort.</li>
  318. <li>Thunderbolt 3 can carry DisplayPort 1.4, so if only I can find the adapter, I should be good to go.</li>
  319. </ul>
  320. <p>Which port does my Macbook have? Easy! Use this Apple-provided diagram:</p>
  321. <figure>
  322. <img src="https://tonsky.me/blog/monitors/ports_diagram.png"/>
  323. </figure>
  324. <p>Okay, so lighting bolt icon means Thunderbolt (not to be confused with Lighting port!), railroad switch means USB-C. Now just look at your Macbook:</p>
  325. <figure>
  326. <img src="https://tonsky.me/blog/monitors/macbook_ports.png"/>
  327. </figure>
  328. <p>I guess you just have to know it ¯\_(ツ)_/¯. Alternatively, one can look at the Apple’s <a href="https://support.apple.com/kb/SP794?locale=en_US">intuitively named page SP794</a>:</p>
  329. <figure>
  330. <img src="https://tonsky.me/blog/monitors/macbook_spec_1.png"/>
  331. </figure>
  332. <figure>
  333. <img src="https://tonsky.me/blog/monitors/macbook_spec_2.png"/>
  334. </figure>
  335. <p>Ok, first of all, what does Thunderbolt 3 (USB-C) mean? Is it Thunderbolt 3 or is it USB-C? This might be a difference between “works flawlessly” and “doesn’t work at all”:</p>
  336. <figure>
  337. <img src="https://tonsky.me/blog/monitors/monitor_ports.png"/>
  338. </figure>
  339. <p>Then it says “DisplayPort over USB-C” (but we have Thunderbolt 3, not USB-C!). It does not specify the DisplayPort version, and it’s useless without it. It also says USB 3.1 Gen 2 is limited by 10 Gb/s, but I guess USB 3 limits do not apply to USB-C? Also, what kind of name is USB 3.1 Gen 2? Was USB 3.2 already taken?</p>
  340. <p>Well, <a href="https://en.wikipedia.org/wiki/Thunderbolt_(interface)#Thunderbolt_3">Wikipedia to the rescue</a>!</p>
  341. <figure>
  342. <img src="https://tonsky.me/blog/monitors/thunderbolt_3.png"/>
  343. </figure>
  344. <p>Turns out Thunderbolt 3 <a href="https://en.wikipedia.org/wiki/Thunderbolt_(interface)#Thunderbolt_3">might or might not carry DisplayPort 1.4</a>. Some of them only go as far as DP 1.2. The Wikipedia article suggests that anything before 2018 definitely won’t work, but after 2018 it might or might not work, depending on a Thunderbolt version. Feeling lost? Use my diagram:</p>
  345. <figure>
  346. <img src="https://tonsky.me/blog/monitors/thunderbolt.png"/>
  347. </figure>
  348. <p>I think we all can agree that this whole Thunderbolt/USB-C situation is a very strong contender for the “Most confusing port standard ever created by humanity”.</p>
  349. <p>Long story short, I was lucky. My Macbook Pro 2019 had the correct port and with Thunderbolt 3 (USB-C) to DisplayPort adapter, everything worked. My understanding is, port versions on devices matter, but cables and adapters do not, as long as they physically fit into the hole. In my case, it was <a href="https://www.mi.com/commutator-dp">Xiaomi USB-C → miniDP</a> converter and miniDP → DP cable.</p>
  350. <figure>
  351. <img src="https://tonsky.me/blog/monitors/converter.png"/>
  352. </figure>
  353. <p>Will it work for you? No idea! I hope so. All I know is that you should make sure your Thunderbolt 3 can carry DisplayPort 1.4. That’s the magical combination.</p>
  354. <h2 id="things-to-look-out-for-macoscontinued">Things to look out for (macOS)—continued</h2>
  355. <p>If that was not confusing enough, there’s more!</p>
  356. <p>Your Macbook has to have a discrete graphics card (I think).<sup id="fnref:2"/> Various Intel UHD / Iris Graphics do not work. eGPU works.</p>
  357. <figure>
  358. <img src="https://tonsky.me/blog/monitors/graphics.png"/>
  359. </figure>
  360. <p>But even if you have the compatible Mac, with compatible ports, compatible cables, this is not enough. Every time I boot my Mac, there’s a ritual I have to perform to get my display to switch to the 120 Hz mode. I call it “120 Hz dance”:</p>
  361. <ol>
  362. <li>Fully boot into macOS. At this point display usually is at 60 Hz.</li>
  363. <li>Go to System Preferences → Displays.</li>
  364. <li>
  365. <p>While holding down Alt / Option key (the one with ⌥ on it), click on “Scaled” resolution.</p>
  366. <figure>
  367. <img src="https://tonsky.me/blog/monitors/settings_1.png"/>
  368. </figure>
  369. </li>
  370. <li>
  371. <p>To get access to Refresh rate chooser, check the “Show low resolution mode” checkbox. L for logic.</p>
  372. <figure>
  373. <img src="https://tonsky.me/blog/monitors/settings_2.png"/>
  374. </figure>
  375. </li>
  376. <li>
  377. <p>Look inside “Refresh Rate”. Most of the time the highest option there is “60 Hz”.</p>
  378. <figure>
  379. <img src="https://tonsky.me/blog/monitors/settings_3.png"/>
  380. </figure>
  381. </li>
  382. <li>Turn display off.</li>
  383. <li>Wait a couple of seconds.</li>
  384. <li>Turn the display on.</li>
  385. <li>
  386. <p>Look again under “Refresh Rate”. Hopefully, there’s now a “119.88 Herz” option.</p>
  387. <figure>
  388. <img src="https://tonsky.me/blog/monitors/settings_4.png"/>
  389. </figure>
  390. </li>
  391. <li>Select “119.88 Herz” in “Refresh Rate”.</li>
  392. <li>You are magnificent.</li>
  393. </ol>
  394. <p>Why is it 119.88 Herz, not 120 Herz? No idea. It seems to work the same. Why can’t macOS remember it? I don’t know. Why doesn’t macOS sees 120 Hz as an option until I turn the monitor off/on? Who knows! The main takeaway is, 120 Hz option might not always appear, but after some dancing around it might, and if it does, it actually works, despite all odds.</p>
  395. <p>The whole situation reminds me of buying 4k display in 2014: there are only a couple of models, ports are confusing, Apple support sucks. Hopefully, in five years 120 Hz will become a standard. Until then we should be grateful that, at great inconvenience, we at least can use modern displays with macOS. Thanks, Apple!</p>
  396. <h1 id="whats-next">What’s next?</h1>
  397. <p>Every human needs a dream. At some point, 4k @ 120 Hz will become the commodity, and we might even see 5k @ 120 Hz and more. We might also see Retina screens with ratios of 21:9<sup id="fnref:3"/> and even 32:9 (more horizontal space), which is always a welcome addition.</p>
  398. <p>But even today you can peek into the future, if you have extra $4,000 to spare. This is <a href="https://www.dell.com/en-us/work/shop/dell-ultrasharp-32-8k-monitor-up3218k/apd/210-alez/monitors-monitor-accessories">Dell UP3218K</a>, world’s first and only 8k monitor:</p>
  399. <figure>
  400. <img src="https://tonsky.me/blog/monitors/dell_up3218k.png"/>
  401. Even on a promo page for 8k display, Dell puts out only 1× photos of it.
  402. </figure>
  403. <p>The pixel density on it is so high (280 PPI) it’s probably best used at 300% scaling (which macOS doesn’t have, of course, but Windows does). It also requires TWO simultaneous DisplayPort cables to work, which is again, a no-go for Macs.</p>
  404. <p>But even at 300% it will still give you an effective logical resolution of 2560×1440, which is substantially more than 1920×1080 of modern 4k displays. More pixel density and bigger resolution! Well, one can dream.</p>
  405. <h1 id="conclusion">Conclusion</h1>
  406. <p>To sum up, this is the best setup for programmers:</p>
  407. <ul>
  408. <li>Text can’t be made look good on low-resolution displays.</li>
  409. <li>High-PPI displays are now a commodity, it’s time to switch.</li>
  410. <li>Notebooks are ok, but a standalone monitor is always better.</li>
  411. <li>4k monitor only makes sense with 2× / 200% scaling.</li>
  412. <li>If you want to go further, there are now affordable 4k @ 120 Hz options.</li>
  413. </ul>
  414. <p>Happy coding!</p>
  415. </main>
  416. </article>
  417. <hr>
  418. <footer>
  419. <p>
  420. <a href="/david/" title="Aller à l’accueil">🏠</a> •
  421. <a href="/david/log/" title="Accès au flux RSS">🤖</a> •
  422. <a href="http://larlet.com" title="Go to my English profile" data-instant>🇨🇦</a> •
  423. <a href="mailto:david%40larlet.fr" title="Envoyer un courriel">📮</a> •
  424. <abbr title="Hébergeur : Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33184162340">🧚</abbr>
  425. </p>
  426. <template id="theme-selector">
  427. <form>
  428. <fieldset>
  429. <legend>Thème</legend>
  430. <label>
  431. <input type="radio" value="auto" name="chosen-color-scheme" checked> Auto
  432. </label>
  433. <label>
  434. <input type="radio" value="dark" name="chosen-color-scheme"> Foncé
  435. </label>
  436. <label>
  437. <input type="radio" value="light" name="chosen-color-scheme"> Clair
  438. </label>
  439. </fieldset>
  440. </form>
  441. </template>
  442. </footer>
  443. <script type="text/javascript">
  444. function loadThemeForm(templateName) {
  445. const themeSelectorTemplate = document.querySelector(templateName)
  446. const form = themeSelectorTemplate.content.firstElementChild
  447. themeSelectorTemplate.replaceWith(form)
  448. form.addEventListener('change', (e) => {
  449. const chosenColorScheme = e.target.value
  450. localStorage.setItem('theme', chosenColorScheme)
  451. toggleTheme(chosenColorScheme)
  452. })
  453. const selectedTheme = localStorage.getItem('theme')
  454. if (selectedTheme && selectedTheme !== 'undefined') {
  455. form.querySelector(`[value="${selectedTheme}"]`).checked = true
  456. }
  457. }
  458. const prefersColorSchemeDark = '(prefers-color-scheme: dark)'
  459. window.addEventListener('load', () => {
  460. let hasDarkRules = false
  461. for (const styleSheet of Array.from(document.styleSheets)) {
  462. let mediaRules = []
  463. for (const cssRule of styleSheet.cssRules) {
  464. if (cssRule.type !== CSSRule.MEDIA_RULE) {
  465. continue
  466. }
  467. // WARNING: Safari does not have/supports `conditionText`.
  468. if (cssRule.conditionText) {
  469. if (cssRule.conditionText !== prefersColorSchemeDark) {
  470. continue
  471. }
  472. } else {
  473. if (cssRule.cssText.startsWith(prefersColorSchemeDark)) {
  474. continue
  475. }
  476. }
  477. mediaRules = mediaRules.concat(Array.from(cssRule.cssRules))
  478. }
  479. // WARNING: do not try to insert a Rule to a styleSheet you are
  480. // currently iterating on, otherwise the browser will be stuck
  481. // in a infinite loop…
  482. for (const mediaRule of mediaRules) {
  483. styleSheet.insertRule(mediaRule.cssText)
  484. hasDarkRules = true
  485. }
  486. }
  487. if (hasDarkRules) {
  488. loadThemeForm('#theme-selector')
  489. }
  490. })
  491. </script>
  492. </body>
  493. </html>