A place to cache linked articles (think custom and personal wayback machine)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.html 30KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681
  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,minimum-scale=1,initial-scale=1,shrink-to-fit=no">
  11. <!-- Required to make a valid HTML5 document. -->
  12. <title>Designing for actual performance (archive) — David Larlet</title>
  13. <!-- Generated from https://realfavicongenerator.net/ such a mess. -->
  14. <link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons/apple-touch-icon.png">
  15. <link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons/favicon-32x32.png">
  16. <link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons/favicon-16x16.png">
  17. <link rel="manifest" href="/manifest.json">
  18. <link rel="mask-icon" href="/static/david/icons/safari-pinned-tab.svg" color="#5bbad5">
  19. <link rel="shortcut icon" href="/static/david/icons/favicon.ico">
  20. <meta name="apple-mobile-web-app-title" content="David Larlet">
  21. <meta name="application-name" content="David Larlet">
  22. <meta name="msapplication-TileColor" content="#da532c">
  23. <meta name="msapplication-config" content="/static/david/icons/browserconfig.xml">
  24. <meta name="theme-color" content="#f0f0ea">
  25. <!-- That good ol' feed, subscribe :p. -->
  26. <link rel=alternate type="application/atom+xml" title=Feed href="/david/log/">
  27. <meta name="robots" content="noindex, nofollow">
  28. <meta content="origin-when-cross-origin" name="referrer">
  29. <!-- Canonical URL for SEO purposes -->
  30. <link rel="canonical" href="https://adamsilver.io/articles/designing-for-actual-performance/">
  31. <style>
  32. /* http://meyerweb.com/eric/tools/css/reset/ */
  33. html, body, div, span,
  34. h1, h2, h3, h4, h5, h6, p, blockquote, pre,
  35. a, abbr, address, big, cite, code,
  36. del, dfn, em, img, ins,
  37. small, strike, strong, tt, var,
  38. dl, dt, dd, ol, ul, li,
  39. fieldset, form, label, legend,
  40. table, caption, tbody, tfoot, thead, tr, th, td,
  41. article, aside, canvas, details, embed,
  42. figure, figcaption, footer, header, hgroup,
  43. menu, nav, output, ruby, section, summary,
  44. time, mark, audio, video {
  45. margin: 0;
  46. padding: 0;
  47. border: 0;
  48. font-size: 100%;
  49. font: inherit;
  50. vertical-align: baseline;
  51. }
  52. /* HTML5 display-role reset for older browsers */
  53. article, aside, details, figcaption, figure,
  54. footer, header, hgroup, menu, nav, section { display: block; }
  55. body { line-height: 1; }
  56. blockquote, q { quotes: none; }
  57. blockquote:before, blockquote:after,
  58. q:before, q:after {
  59. content: '';
  60. content: none;
  61. }
  62. table {
  63. border-collapse: collapse;
  64. border-spacing: 0;
  65. }
  66. /* http://practicaltypography.com/equity.html */
  67. /* https://calendar.perfplanet.com/2016/no-font-face-bulletproof-syntax/ */
  68. /* https://www.filamentgroup.com/lab/js-web-fonts.html */
  69. @font-face {
  70. font-family: 'EquityTextB';
  71. src: url('/static/david/css/fonts/Equity-Text-B-Regular-webfont.woff2') format('woff2'),
  72. url('/static/david/css/fonts/Equity-Text-B-Regular-webfont.woff') format('woff');
  73. font-weight: 300;
  74. font-style: normal;
  75. font-display: swap;
  76. }
  77. @font-face {
  78. font-family: 'EquityTextB';
  79. src: url('/static/david/css/fonts/Equity-Text-B-Italic-webfont.woff2') format('woff2'),
  80. url('/static/david/css/fonts/Equity-Text-B-Italic-webfont.woff') format('woff');
  81. font-weight: 300;
  82. font-style: italic;
  83. font-display: swap;
  84. }
  85. @font-face {
  86. font-family: 'EquityTextB';
  87. src: url('/static/david/css/fonts/Equity-Text-B-Bold-webfont.woff2') format('woff2'),
  88. url('/static/david/css/fonts/Equity-Text-B-Bold-webfont.woff') format('woff');
  89. font-weight: 700;
  90. font-style: normal;
  91. font-display: swap;
  92. }
  93. @font-face {
  94. font-family: 'ConcourseT3';
  95. src: url('/static/david/css/fonts/concourse_t3_regular-webfont-20190806.woff2') format('woff2'),
  96. url('/static/david/css/fonts/concourse_t3_regular-webfont-20190806.woff') format('woff');
  97. font-weight: 300;
  98. font-style: normal;
  99. font-display: swap;
  100. }
  101. /* http://practice.typekit.com/lesson/caring-about-opentype-features/ */
  102. body {
  103. /* http://www.cssfontstack.com/ Palatino 99% Win 86% Mac */
  104. font-family: "EquityTextB", Palatino, serif;
  105. background-color: #f0f0ea;
  106. color: #07486c;
  107. font-kerning: normal;
  108. -moz-osx-font-smoothing: grayscale;
  109. -webkit-font-smoothing: subpixel-antialiased;
  110. text-rendering: optimizeLegibility;
  111. font-variant-ligatures: common-ligatures contextual;
  112. font-feature-settings: "kern", "liga", "clig", "calt";
  113. }
  114. pre, code, kbd, samp, var, tt {
  115. font-family: 'TriplicateT4c', monospace;
  116. }
  117. em {
  118. font-style: italic;
  119. color: #323a45;
  120. }
  121. strong {
  122. font-weight: bold;
  123. color: black;
  124. }
  125. nav {
  126. background-color: #323a45;
  127. color: #f0f0ea;
  128. display: flex;
  129. justify-content: space-around;
  130. padding: 1rem .5rem;
  131. }
  132. nav:last-child {
  133. border-bottom: 1vh solid #2d7474;
  134. }
  135. nav a {
  136. color: #f0f0ea;
  137. }
  138. nav abbr {
  139. border-bottom: 1px dotted white;
  140. }
  141. h1 {
  142. border-top: 1vh solid #2d7474;
  143. border-bottom: .2vh dotted #2d7474;
  144. background-color: #e3e1e1;
  145. color: #323a45;
  146. text-align: center;
  147. padding: 5rem 0 4rem 0;
  148. width: 100%;
  149. font-family: 'ConcourseT3';
  150. display: flex;
  151. flex-direction: column;
  152. }
  153. h1.single {
  154. padding-bottom: 10rem;
  155. }
  156. h1 span {
  157. position: absolute;
  158. top: 1vh;
  159. left: 20%;
  160. line-height: 0;
  161. }
  162. h1 span a {
  163. line-height: 1.7;
  164. padding: 1rem 1.2rem .6rem 1.2rem;
  165. border-radius: 0 0 6% 6%;
  166. background: #2d7474;
  167. font-size: 1.3rem;
  168. color: white;
  169. text-decoration: none;
  170. }
  171. h2 {
  172. margin: 4rem 0 1rem;
  173. border-top: .2vh solid #2d7474;
  174. padding-top: 1vh;
  175. }
  176. h3 {
  177. text-align: center;
  178. margin: 3rem 0 .75em;
  179. }
  180. hr {
  181. height: .4rem;
  182. width: .4rem;
  183. border-radius: .4rem;
  184. background: #07486c;
  185. margin: 2.5rem auto;
  186. }
  187. time {
  188. display: bloc;
  189. margin-left: 0 !important;
  190. }
  191. ul, ol {
  192. margin: 2rem;
  193. }
  194. ul {
  195. list-style-type: square;
  196. }
  197. a {
  198. text-decoration-skip-ink: auto;
  199. text-decoration-thickness: 0.05em;
  200. text-underline-offset: 0.09em;
  201. }
  202. article {
  203. max-width: 50rem;
  204. display: flex;
  205. flex-direction: column;
  206. margin: 2rem auto;
  207. }
  208. article.single {
  209. border-top: .2vh dotted #2d7474;
  210. margin: -6rem auto 1rem auto;
  211. background: #f0f0ea;
  212. padding: 2rem;
  213. }
  214. article p:last-child {
  215. margin-bottom: 1rem;
  216. }
  217. p {
  218. padding: 0 .5rem;
  219. margin-left: 3rem;
  220. }
  221. p + p,
  222. figure + p {
  223. margin-top: 2rem;
  224. }
  225. blockquote {
  226. background-color: #e3e1e1;
  227. border-left: .5vw solid #2d7474;
  228. display: flex;
  229. flex-direction: column;
  230. align-items: center;
  231. padding: 1rem;
  232. margin: 1.5rem;
  233. }
  234. blockquote cite {
  235. font-style: italic;
  236. }
  237. blockquote p {
  238. margin-left: 0;
  239. }
  240. figure {
  241. border-top: .2vh solid #2d7474;
  242. background-color: #e3e1e1;
  243. text-align: center;
  244. padding: 1.5rem 0;
  245. margin: 1rem 0 0;
  246. font-size: 1.5rem;
  247. width: 100%;
  248. }
  249. figure img {
  250. max-width: 250px;
  251. max-height: 250px;
  252. border: .5vw solid #323a45;
  253. padding: 1px;
  254. }
  255. figcaption {
  256. padding: 1rem;
  257. line-height: 1.4;
  258. }
  259. aside {
  260. display: flex;
  261. flex-direction: column;
  262. background-color: #e3e1e1;
  263. padding: 1rem 0;
  264. border-bottom: .2vh solid #07486c;
  265. }
  266. aside p {
  267. max-width: 50rem;
  268. margin: 0 auto;
  269. }
  270. /* https://fvsch.com/code/css-locks/ */
  271. p, li, pre, code, kbd, samp, var, tt, time, details, figcaption {
  272. font-size: 1rem;
  273. line-height: calc( 1.5em + 0.2 * 1rem );
  274. }
  275. h1 {
  276. font-size: 1.9rem;
  277. line-height: calc( 1.2em + 0.2 * 1rem );
  278. }
  279. h2 {
  280. font-size: 1.6rem;
  281. line-height: calc( 1.3em + 0.2 * 1rem );
  282. }
  283. h3 {
  284. font-size: 1.35rem;
  285. line-height: calc( 1.4em + 0.2 * 1rem );
  286. }
  287. @media (min-width: 20em) {
  288. /* The (100vw - 20rem) / (50 - 20) part
  289. resolves to 0-1rem, depending on the
  290. viewport width (between 20em and 50em). */
  291. p, li, pre, code, kbd, samp, var, tt, time, details, figcaption {
  292. font-size: calc( 1rem + .6 * (100vw - 20rem) / (50 - 20) );
  293. line-height: calc( 1.5em + 0.2 * (100vw - 50rem) / (20 - 50) );
  294. margin-left: 0;
  295. }
  296. h1 {
  297. font-size: calc( 1.9rem + 1.5 * (100vw - 20rem) / (50 - 20) );
  298. line-height: calc( 1.2em + 0.2 * (100vw - 50rem) / (20 - 50) );
  299. }
  300. h2 {
  301. font-size: calc( 1.5rem + 1.5 * (100vw - 20rem) / (50 - 20) );
  302. line-height: calc( 1.3em + 0.2 * (100vw - 50rem) / (20 - 50) );
  303. }
  304. h3 {
  305. font-size: calc( 1.35rem + 1.5 * (100vw - 20rem) / (50 - 20) );
  306. line-height: calc( 1.4em + 0.2 * (100vw - 50rem) / (20 - 50) );
  307. }
  308. }
  309. @media (min-width: 50em) {
  310. /* The right part of the addition *must* be a
  311. rem value. In this example we *could* change
  312. the whole declaration to font-size:2.5rem,
  313. but if our baseline value was not expressed
  314. in rem we would have to use calc. */
  315. p, li, pre, code, kbd, samp, var, tt, time, details, figcaption {
  316. font-size: calc( 1rem + .6 * 1rem );
  317. line-height: 1.5em;
  318. }
  319. p, li, pre, details {
  320. margin-left: 3rem;
  321. }
  322. h1 {
  323. font-size: calc( 1.9rem + 1.5 * 1rem );
  324. line-height: 1.2em;
  325. }
  326. h2 {
  327. font-size: calc( 1.5rem + 1.5 * 1rem );
  328. line-height: 1.3em;
  329. }
  330. h3 {
  331. font-size: calc( 1.35rem + 1.5 * 1rem );
  332. line-height: 1.4em;
  333. }
  334. figure img {
  335. max-width: 500px;
  336. max-height: 500px;
  337. }
  338. }
  339. figure.unsquared {
  340. margin-bottom: 1.5rem;
  341. }
  342. figure.unsquared img {
  343. height: inherit;
  344. }
  345. @media print {
  346. body { font-size: 100%; }
  347. a:after { content: " (" attr(href) ")"; }
  348. a, a:link, a:visited, a:after {
  349. text-decoration: underline;
  350. text-shadow: none !important;
  351. background-image: none !important;
  352. background: white;
  353. color: black;
  354. }
  355. abbr[title] { border-bottom: 0; }
  356. abbr[title]:after { content: " (" attr(title) ")"; }
  357. img { page-break-inside: avoid; }
  358. @page { margin: 2cm .5cm; }
  359. h1, h2, h3 { page-break-after: avoid; }
  360. p3 { orphans: 3; widows: 3; }
  361. img {
  362. max-width: 250px !important;
  363. max-height: 250px !important;
  364. }
  365. nav, aside { display: none; }
  366. }
  367. ul.with_columns {
  368. column-count: 1;
  369. }
  370. @media (min-width: 20em) {
  371. ul.with_columns {
  372. column-count: 2;
  373. }
  374. }
  375. @media (min-width: 50em) {
  376. ul.with_columns {
  377. column-count: 3;
  378. }
  379. }
  380. ul.with_two_columns {
  381. column-count: 1;
  382. }
  383. @media (min-width: 20em) {
  384. ul.with_two_columns {
  385. column-count: 1;
  386. }
  387. }
  388. @media (min-width: 50em) {
  389. ul.with_two_columns {
  390. column-count: 2;
  391. }
  392. }
  393. .gallery {
  394. display: flex;
  395. flex-wrap: wrap;
  396. justify-content: space-around;
  397. }
  398. .gallery figure img {
  399. margin-left: 1rem;
  400. margin-right: 1rem;
  401. }
  402. .gallery figure figcaption {
  403. font-family: 'ConcourseT3'
  404. }
  405. footer {
  406. font-family: 'ConcourseT3';
  407. display: flex;
  408. flex-direction: column;
  409. border-top: 3px solid white;
  410. padding: 4rem 0;
  411. background-color: #07486c;
  412. color: white;
  413. }
  414. footer > * {
  415. max-width: 50rem;
  416. margin: 0 auto;
  417. }
  418. footer a {
  419. color: #f1c40f;
  420. }
  421. footer .avatar {
  422. width: 200px;
  423. height: 200px;
  424. border-radius: 50%;
  425. float: left;
  426. -webkit-shape-outside: circle();
  427. shape-outside: circle();
  428. margin-right: 2rem;
  429. padding: 2px 5px 5px 2px;
  430. background: white;
  431. border-left: 1px solid #f1c40f;
  432. border-top: 1px solid #f1c40f;
  433. border-right: 5px solid #f1c40f;
  434. border-bottom: 5px solid #f1c40f;
  435. }
  436. </style>
  437. <h1>
  438. <span><a id="jumper" href="#jumpto" title="Un peu perdu ?">?</a></span>
  439. Designing for actual performance (archive)
  440. <time>Pour la pérennité des contenus liés. Non-indexé, retrait sur simple email.</time>
  441. </h1>
  442. <section>
  443. <article>
  444. <h3><a href="https://adamsilver.io/articles/designing-for-actual-performance/">Source originale du contenu</a></h3>
  445. <p>This is how it goes. We put a load of shit into a single web page. This makes the page slow. Slow to load, slow to render. Slow.</p>
  446. <p>Instead of getting rid of the shit, we blame the page refresh. There's only one way to avoid the page refresh and that's AJAX.</p>
  447. <p>However, AJAX still needs to render new (parts of) screens. More crucially it still has to make a request to the server. That's not all—there are penalties in using AJAX and it doesn't necessarily result in faster experiences.</p>
  448. <p>Firstly, making requests; handling different responses; traversing the document tree; and injecting HTML requires <em>more</em> code to be sent initally. This also needs to be evaluated and executed on the client.</p>
  449. <p>Secondly, AJAX engineers away progressive rendering—which by the way—browsers do for free. To reinstate this functionality we resort to <a href="https://jakearchibald.com/2016/fun-hacks-faster-content/">hacks</a> that need yet more code. (Plus nobody uses the hack anyway.)</p>
  450. <p>Thirdly, using AJAX means we have to give users another way of knowing that something is being loaded. Again, browsers give us a really good loading indicator for free.</p>
  451. <p>With AJAX, we need to design and build a custom one. Not only is this more work and more code, but they are an inferior replacement for those provided by browsers.</p>
  452. <p>This is because a browser's indicator displays progress. That is, a user can tell how long until the request finishes. Custom loading indicators or <em>spinners</em> don't display progress, so users get frustrated and click again causing further delays.</p>
  453. <p>And custom indicators are unfamiliar as the look and placement differs from site to site. Conversely, the browser's indicator appears in the same place and behaves the same for every website. This creates a familiar and informative experience that we should be loathed to forgo.</p>
  454. <p>This doesn't mean AJAX is <em>bad</em>. AJAX is useful depending on the situation as it avoids requesting the same assets over and over and may well render faster if updating a small segment of the page. But it's not a solution to slow-loading pages. At best it patches over the problems that lie beneath.</p>
  455. <p>The real problem is that we've designed something that can never be fast. Therefore the question really is <em>how do we design for performance?</em></p>
  456. <h2 id="1.-simplify-the-interface">1. Simplify the interface</h2>
  457. <p>The best way to make pages fast, is to have less stuff in them. You'd be forgiven for wanting to punch me in the face as this is obvious. And yet <a href="https://www.keycdn.com/support/the-growth-of-web-page-size/">web pages keep getting fatter and fatter</a>.</p>
  458. <p>Do we need background videos, modal dialogs and social media buttons plastered everywhere? The answer from the people is a resounding <em>no</em>. The fastest feature is one we never build.</p>
  459. <p>What about the way we design components? Hamburger menus, tabs, carousels, accordions, image galleries and expanding panels. All these things have one thing in common. They hide stuff.</p>
  460. <p>Designers are obsessed with patterns that save space and look clean. A clean interface is good but not at the cost of clarity. If pages only contain the essential, then there should be little and maybe even nothing to hide.</p>
  461. <p>Effort aside, designing fully responsive and inclusive components results in <em>more</em> code. More code that users rarely appreciate. After all, it slows the page down and requires the user to exert energy revealing the hidden content.</p>
  462. <p>Heydon Pickering coined the seemingly satirical term <em>Unprogressive Non-enhancement</em>. This is how he explains it:</p>
  463. <blockquote>
  464. <p>You take some structured content, which follows the vertical flow of the document in a way that everyone understands.<br/><br/><br/>
  465. Which people traverse easily by either dragging their scroll bar with their mouse, or operating the keyboard using the up and down keys, or using the spacebar.<br/><br/><br/>
  466. Or if they're using a touch device, simply flicking backwards and forwards in that easy way that we've all become used to. <strong>What you do is you take that, and you fucking well leave it alone.</strong></p>
  467. </blockquote>
  468. <p>Letting things stack naturally is a good start. Not only does this embrace the way the web works—it makes for a remarkably inclusive and fast experience.</p>
  469. <p><em>A fast experience, by the way, is a vital aspect of designing inclusive experiences. Some people don't have fast connections and this shouldn't cause exclusion.</em></p>
  470. <p>Letting things stack isn't our <em>only</em> option. We can chunk stuff across multiple pages. Once pages have little on them the page refresh ‘problem’ is no longer a problem. Pages are fast by design. Sometimes to the point where the <a href="http://uncrate.com">page refresh is unnoticeable</a>.</p>
  471. <p>With regards to longish complex forms (or even shortish ones) there is <a href="https://www.smashingmagazine.com/2017/05/better-form-design-one-thing-per-page/">One Thing Per Page</a> which I've spoken and written about before.</p>
  472. <p>But this pattern isn't reserved for forms. A typical product page contains an image carousel, description, add to basket form, other details, shipping information, related products, ratings and comments. We can split this up too.</p>
  473. <p>Most users don't read every single aspect of a product, every time they visit the page. Instead give users a lightweight page and the choice to drill down further.</p>
  474. <p>Give users one high-definition image <em>without</em> a carousel. Then let users click <em>show all</em> which would show all the images in a page of its own. No Javascript is needed either, saving yet more code. Let the content flow.</p>
  475. <p>This uses the natural building blocks of the web as a form of <a href="https://medium.muz.li/design-technique-progressive-disclosure-1980def8dc97?gi=361cf4735361">progressive disclosure</a>. Ultimately, this speeds things up drastically.</p>
  476. <p>People on expensive data contracts benefit too. They can choose to see all the images by following the link or they can wait until they are connected to WI-FI.</p>
  477. <p>It's easier to share page content or imagery this way too. Sending users to a page where most of the stuff is hidden is problematic.</p>
  478. <p>Tabs: If stuff is hidden by default, how important is its existence on this page? Or if the tab contains a small amount of content just show it. Or consider putting it on a separate page.</p>
  479. <p>If you're feeling brave, put your site's <a href="http://yaronschoen.com/table-of-contents/">navigation menu on a separate page</a> too. The page is light and loads quickly. Maybe this is too far. Maybe not.</p>
  480. <p>Modal dialogs are often misused. All too often they contain too much content that would be better off as a new page anyway. This improves performance and doesn't break the back button (like a dialog often does).</p>
  481. <p>Less code, less problems and a faster, better experience. I'm seeing a theme here. Scroll jacking, <a href="/articles/floating-labels-are-problematic/">floating labels</a>, <a href="http://adrianroselli.com/2016/12/dont-re-create-browser-features.html">font-size widgets</a>, <a href="http://usabilitygeek.com/ux-designers-ditch-sidebar-2016/">side bars</a>, custom select boxes—kill.</p>
  482. <h2 id="2.-reduce-code">2. Reduce code</h2>
  483. <p>By simplifying the interface we've already reduced the code by literally not writing any. But coding the remaining features brings forth a different opportunity—to write less code.</p>
  484. <h3 id="create-lean-html">Create lean HTML</h3>
  485. <p>Sometimes developers use the wrong element. A <code>&lt;button&gt;</code> is half the size of <code>&lt;div role="button" tabinidex="0"&gt;</code> and doesn't require script to make it accessible again.</p>
  486. <p><a href="https://csscreator.com/divitis">Divitus</a> is an antiquated buzzword but its still prevalent today. We often use <a href="http://getbootstrap.com/components/#navbar-brand-image">additional elements unncessarily</a>. These make the request longer to make, parse and render. We should be able to justify the existence of every element.</p>
  487. <p>Classitus is the use of extra classes. Extra classes may decrease the size of CSS but they signifcantly increase the size of HTML.</p>
  488. <p>Ensuring HTML is small is important. Unlike CSS, it can't be easily cached. This is because it's likely to contain personalised and dynamic content. This in turn encourages the <a href="/articles/dont-use-ajax-for-personalised-content/">misuse of AJAX</a>.</p>
  489. <p>We may also find ourselves adding various <a href="(https://silktide.com/i-thought-title-text-improved-accessibility-i-was-wrong/)">attributes in the name of accessibility</a>. But, they aren't always necessary or valuable, and they add further weight to the page.</p>
  490. <p>Similarly, the first rule of ARIA is not to use it. To associate errors to a form control we might use <code>aria-describedby</code>:</p>
  491. <pre><code>&lt;label for="age"&gt;
  492. Age
  493. &lt;/label&gt;
  494. &lt;div id="age_error"&gt;Enter your age&lt;/div&gt;
  495. &lt;input id="age" aria-describedby="age_error"&gt;
  496. </code></pre>
  497. <p>Instead putting the error in the label is more performant <em>and</em> more inclusive:</p>
  498. <pre><code>&lt;label for="age"&gt;
  499. Age
  500. &lt;div&gt;Enter your age&lt;/div&gt;
  501. &lt;/label&gt;
  502. &lt;input id="age"&gt;
  503. </code></pre>
  504. <p>Using <a href="/articles/dont-initialise-javascript-automagically/">HTML attributes to automagically initialise script</a> increases the HTML (and has other problems too).</p>
  505. <p>Don't add HTML hooks just for automated functional tests. <a href="https://maintainablecss.com/chapters/semantics/">Semantic hooks serve everyone's purpose equally</a>.</p>
  506. <h3 id="simplify-your-design-system">Simplify your design system</h3>
  507. <p>Government Digital Services design simple websites. Most things are left aligned and stack naturally. In this case we may be able to <a href="https://www.smashingmagazine.com/2016/11/css-inheritance-cascade-global-scope-new-old-worst-best-friends/">avoid CSS classes altogether</a> which further proves that a simple interface is a performant one.</p>
  508. <h3 id="use-less-script">Use less script</h3>
  509. <p><a href="http://openmymind.net/2012/5/30/Client-Side-vs-Server-Side-Rendering/">Single pages applications don't necessarily render faster</a> and come with a whole <a href="/articles/the-disadvantages-of-single-page-applications/">bunch of problems</a>. But it's not just rendering. It takes a lot of code to create a robust client-side application, that typically prompts developers to use a large framework.</p>
  510. <p>But maybe we don't need the whole framework. Putting that burden on the user is an act of negligence. Starting with an entire framework or library puts you on the back foot.</p>
  511. <p><a href="http://www.heydonworks.com/article/look-at-this-shitty-tweet-button">Twitter's tweet button script weighs 50k</a>. We can do the same thing with 0 bytes of script by using a simple link.</p>
  512. <h3 id="use-preprocessors-responsibly">Use preprocessors responsibly</h3>
  513. <p><a href="https://jaketrent.com/post/cons-css-preprocessors/#file-size-is-deceiving">Preprocessors are deceitful because they can generate large CSS</a>.</p>
  514. <h3 id="use-content-breakpoints">Use content breakpoints</h3>
  515. <p>Often a module may need just one breakpoint or even no breakpoints. Designing to a predefined set of breakpoints encourages the unnecessary tweaking of a design that results in more code.</p>
  516. <h2 id="3.-images">3. Images</h2>
  517. <p>Not everyone has access to the <a href="https://www.smashingmagazine.com/2017/03/world-wide-web-not-wealthy-western-web-part-1/">world western web</a>. Not everybody is on high-end devices either. So, if you really need that high resolution image help the user by:</p>
  518. <h2 id="4.-backend-stuff">4. Backend stuff</h2>
  519. <p>Enable <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding#Chunked_encoding">chunking</a> and progressive rendering. Don't engineer it away.</p>
  520. <p>Use Command Query Responsibility Segregation to make database queries fast (good for sites that have more reads than writes).</p>
  521. <p>Use a Content Delivery Network for your static resources. And cache HTML and AJAX responses too.</p>
  522. <p>Cache assets with long expiry dates so that users don't have to download assets again.</p>
  523. <p>Place scripts at the bottom and use <code>async</code> and <code>defer</code> attributes. Async is good for completley independent scripts that can run later like analytics.</p>
  524. <p>Use <a href="https://www.troyhunt.com/i-wanna-go-fast-https-massive-speed-advantage/">HTTPS over HTTP2</a> with Gzip compression. Gzip, by the way, works better with a well-designed and consistent design system—the more HTML is repeated the better the compression.</p>
  525. <p>Use <a href="https://medium.com/reloading/preload-prefetch-and-priorities-in-chrome-776165961bbf">preload and prefetch</a> where appropriate. Addy Osmani says <em>preload resources you have high-confidence will be used in the current page. Prefetch resources likely to be used for future navigations across multiple navigation boundaries.</em></p>
  526. <h2 id="summary">Summary</h2>
  527. <p>You know what's better than perceived performance? Actual performance. Avoid techniques that merely provide a mirage of speed.</p>
  528. <p>Instead, declutter and optimise the foundations of your design system which will result in less weight, less complexity, less distraction, less hassle and ultimately, less <a href="http://deathtobullshit.com/">bull shit</a>.</p>
  529. <p>Together, these techniques produce fast and simple experiences that make users feel awesome.</p>
  530. </article>
  531. </section>
  532. <nav id="jumpto">
  533. <p>
  534. <a href="/david/blog/">Accueil du blog</a> |
  535. <a href="https://adamsilver.io/articles/designing-for-actual-performance/">Source originale</a> |
  536. <a href="/david/stream/2019/">Accueil du flux</a>
  537. </p>
  538. </nav>
  539. <footer>
  540. <div>
  541. <img src="/static/david/david-larlet-avatar.jpg" loading="lazy" class="avatar" width="200" height="200">
  542. <p>
  543. Bonjour/Hi!
  544. Je suis <a href="/david/" title="Profil public">David&nbsp;Larlet</a>, je vis actuellement à Montréal et j’alimente cet espace depuis 15 ans. <br>
  545. Si tu as apprécié cette lecture, n’hésite pas à poursuivre ton exploration. Par exemple via les <a href="/david/blog/" title="Expériences bienveillantes">réflexions bimestrielles</a>, la <a href="/david/stream/2019/" title="Pensées (dés)articulées">veille hebdomadaire</a> ou en t’abonnant au <a href="/david/log/" title="S’abonner aux publications via RSS">flux RSS</a> (<a href="/david/blog/2019/flux-rss/" title="Tiens c’est quoi un flux RSS ?">so 2005</a>).
  546. </p>
  547. <p>
  548. Je m’intéresse à la place que je peux avoir dans ce monde. En tant qu’humain, en tant que membre d’une famille et en tant qu’associé d’une coopérative. De temps en temps, je fais aussi des <a href="https://github.com/davidbgk" title="Principalement sur Github mais aussi ailleurs">trucs techniques</a>. Et encore plus rarement, <a href="/david/talks/" title="En ce moment je laisse plutôt la place aux autres">j’en parle</a>.
  549. </p>
  550. <p>
  551. Voici quelques articles choisis :
  552. <a href="/david/blog/2019/faire-equipe/" title="Accéder à l’article complet">Faire équipe</a>,
  553. <a href="/david/blog/2018/bivouac-automnal/" title="Accéder à l’article complet">Bivouac automnal</a>,
  554. <a href="/david/blog/2018/commodite-effondrement/" title="Accéder à l’article complet">Commodité et effondrement</a>,
  555. <a href="/david/blog/2017/donnees-communs/" title="Accéder à l’article complet">Des données aux communs</a>,
  556. <a href="/david/blog/2016/accompagner-enfant/" title="Accéder à l’article complet">Accompagner un enfant</a>,
  557. <a href="/david/blog/2016/senior-developer/" title="Accéder à l’article complet">Senior developer</a>,
  558. <a href="/david/blog/2016/illusion-sociale/" title="Accéder à l’article complet">L’illusion sociale</a>,
  559. <a href="/david/blog/2016/instantane-scopyleft/" title="Accéder à l’article complet">Instantané Scopyleft</a>,
  560. <a href="/david/blog/2016/enseigner-web/" title="Accéder à l’article complet">Enseigner le Web</a>,
  561. <a href="/david/blog/2016/simplicite-defaut/" title="Accéder à l’article complet">Simplicité par défaut</a>,
  562. <a href="/david/blog/2016/minimalisme-esthetique/" title="Accéder à l’article complet">Minimalisme et esthétique</a>,
  563. <a href="/david/blog/2014/un-web-omni-present/" title="Accéder à l’article complet">Un web omni-présent</a>,
  564. <a href="/david/blog/2014/manifeste-developpeur/" title="Accéder à l’article complet">Manifeste de développeur</a>,
  565. <a href="/david/blog/2013/confort-convivialite/" title="Accéder à l’article complet">Confort et convivialité</a>,
  566. <a href="/david/blog/2013/testament-numerique/" title="Accéder à l’article complet">Testament numérique</a>,
  567. et <a href="/david/blog/" title="Accéder aux archives">bien d’autres…</a>
  568. </p>
  569. <p>
  570. On peut <a href="mailto:david%40larlet.fr" title="Envoyer un courriel">échanger par courriel</a>. Si éventuellement tu souhaites que l’on travaille ensemble, tu devrais commencer par consulter le <a href="http://larlet.com">profil dédié à mon activité professionnelle</a> et/ou contacter directement <a href="http://scopyleft.fr/">scopyleft</a>, la <abbr title="Société coopérative et participative">SCOP</abbr> dont je fais partie depuis six ans. Je recommande au préalable de lire <a href="/david/blog/2018/cout-site/" title="Attention ce qui va suivre peut vous choquer">combien coûte un site</a> et pourquoi je suis plutôt favorable à une <a href="/david/pro/devis/" title="Discutons-en !">non-demande de devis</a>.
  571. </p>
  572. <p>
  573. Je ne traque pas ta navigation mais mon
  574. <abbr title="Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33.184162340">hébergeur</abbr>
  575. conserve des logs d’accès.
  576. </p>
  577. </div>
  578. </footer>
  579. <script type="text/javascript">
  580. ;(_ => {
  581. const jumper = document.getElementById('jumper')
  582. jumper.addEventListener('click', e => {
  583. e.preventDefault()
  584. const anchor = e.target.getAttribute('href')
  585. const targetEl = document.getElementById(anchor.substring(1))
  586. targetEl.scrollIntoView({behavior: 'smooth'})
  587. })
  588. })()
  589. </script>