<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>decodeuri</title>
    <description>David Moulton, front end developer, blogs here.
</description>
    <link>http://decodeuri.net/</link>
    <atom:link href="http://decodeuri.net/feed.xml" rel="self" type="application/rss+xml" />
    <pubDate>Tue, 25 Sep 2018 10:22:50 +0000</pubDate>
    <lastBuildDate>Tue, 25 Sep 2018 10:22:50 +0000</lastBuildDate>
    <generator>Jekyll v3.7.4</generator>
    
      <item>
        <title>Web typography workshop with Rich Rutter</title>
        <description>&lt;p&gt;Rich Rutter is a veteran web typography expert. Back in 2004 he proposed &lt;a href=&quot;http://clagnut.com/blog/348/&quot;&gt;the 62.5% font sizing trick&lt;/a&gt; which quickly became an established technique to make it easier to reason about using ems when sizing fonts on the web. In 2018 he’s literally written &lt;a href=&quot;http://www.book.webtypography.net/&quot;&gt;the book on web typography&lt;/a&gt;. When I saw this guy was running a workshop at Generate London this year, I had to go! What follows is a lightly edited note-dump to help me remember what I learned.&lt;/p&gt;

&lt;p&gt;Frequent references to &lt;a href=&quot;https://typographica.org/typography-books/the-elements-of-typographic-style-4th-edition/&quot;&gt;Bringhurst&lt;/a&gt;, probably worth a re-read.&lt;/p&gt;

&lt;p&gt;Firefox has the best font support, so for best understanding, try things out in &lt;a href=&quot;https://www.mozilla.org/en-US/firefox/developer/&quot;&gt;Firefox Developer Edition&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;readability&quot;&gt;Readability&lt;/h2&gt;
&lt;p&gt;Relies on the measure, line-height and font-size. If one changes, the other(s) may need to be adjusted to maintain readability.&lt;/p&gt;

&lt;p&gt;Bringhurst says convention considers a readable measure to be between 45-75 characters. Assuming 1em is about the width of two characters, 75 characters comes in at about 38em.&lt;/p&gt;

&lt;p&gt;Reminder: CSS line height is not leading: space imposed by &lt;code class=&quot;highlighter-rouge&quot;&gt;line-height&lt;/code&gt; is distributed equally above and below the text.&lt;/p&gt;

&lt;p&gt;For shorter line lengths, line height can be increased slightly, but it’s best to just pick one value that works well enough across the possible widths.&lt;/p&gt;

&lt;p&gt;You may need to adjust &lt;code class=&quot;highlighter-rouge&quot;&gt;line-height&lt;/code&gt; when using different fonts, test by eye.&lt;/p&gt;

&lt;p&gt;Adjust the font size if required, different overall glyph heights and different x-heights will determine what’s required.&lt;/p&gt;

&lt;p&gt;The “aspect value” is the ratio of x-height to font size. If two different typefaces are being displayed at such sizes that they have the same aspect value, they are likely to look the same size, even when they’re not. Tool for calculating aspect value: &lt;a href=&quot;http://clagnut.com/sandbox/font-size-adjust-ex.html&quot;&gt;http://clagnut.com/sandbox/font-size-adjust-ex.html&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Will be able to use &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/font-size-adjust&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;font-size-adjust&lt;/code&gt;&lt;/a&gt; for this in the future, but not enough browser support yet.&lt;/p&gt;

&lt;h2 id=&quot;reading-distance&quot;&gt;Reading distance&lt;/h2&gt;

&lt;p&gt;Different reading contexts often involve different reading distances. For example reading the news on your phone packed in like cattle on a standing-room-only commuter train, you’re likely not to be the same distance from the screen as when you’re reading that fancy online design magazine on yer massive 4k desktop monitor.&lt;/p&gt;

&lt;p&gt;Arcminutes are units used to express perceived size: it’s a measure of angle which takes distance into account. As reading distance increases, the physical font size needs to be increased in order to maintain the same perceived size.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://sizecalc.com&quot;&gt;Sizecalc&lt;/a&gt; can help, it’s “a tool for calculating and visualizing the relationships between viewing distance, physical size, and perceived size”.&lt;/p&gt;

&lt;p&gt;Using sizecalc, we can determine that someone reading a book set in 10pt type, holding it a comfortable 40cm from their eyes, perceives the size to be 30 arcminutes. This is about the same as someone reading on phone (apparently). Can’t always rely on devices reporting physical size though. For example the iPad and the iPad mini both report the same size via media queries, even though they are very different physical sizes. [Difference between device pixels and CSS pixels?]&lt;/p&gt;

&lt;p&gt;Five arcminutes is about the smallest perceived size of text that we could read.&lt;/p&gt;

&lt;p&gt;Can also use sizecalc to determine that the moon at its perigee (221,559 miles), would have to have writing 322 miles high in order to be read from the surface of the earth (even ignoring any atmospherics etc.) Typography in space FTW! :-D&lt;/p&gt;

&lt;h2 id=&quot;type-size&quot;&gt;Type size&lt;/h2&gt;

&lt;p&gt;Set text in rems.&lt;/p&gt;

&lt;p&gt;Don’t neglect to set text at display sizes where appropriate, even on smaller screens.&lt;/p&gt;

&lt;p&gt;Set type using a scale to ensure a consistent visual hierarchy.&lt;/p&gt;

&lt;p&gt;Examples of scales:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;ios scale: &lt;code class=&quot;highlighter-rouge&quot;&gt;32, 24, 19, 16, 13&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;classic: &lt;code class=&quot;highlighter-rouge&quot;&gt;36, 24, 18, 16, 14&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;16/9: &lt;code class=&quot;highlighter-rouge&quot;&gt;90, 51, 28, 16, 9&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href=&quot;modularscale.com&quot;&gt;modularscale.com&lt;/a&gt; is great for exploring possible scales you might use.&lt;/p&gt;

&lt;p&gt;Can use the same scale for different screen widths, but miss out some points in the scale on larger screens in order to get the exageration in scale that can work well when a lot of screen space to play with.&lt;/p&gt;

&lt;p&gt;Or you can use different scales for different widths. Rich likes to do this so he can focus on the different purposes of the scales which the different widths impose.&lt;/p&gt;

&lt;p&gt;Watch out for line height on headings: the large line height often applied to larger headings can often make one heading look like two headings when it wraps. To get around this, set a small line height for the heading, and organise the vertical space above and/or below it with &lt;code class=&quot;highlighter-rouge&quot;&gt;margin&lt;/code&gt;s.&lt;/p&gt;

&lt;p&gt;You can size display text as you would an image, so you can use e.g. &lt;code class=&quot;highlighter-rouge&quot;&gt;vw&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;vmin&lt;/code&gt; units to size the &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;h1&amp;gt;&lt;/code&gt;. Note that elements styled solely with viewport units aren’t zoomable, so use calc, e.g. &lt;code class=&quot;highlighter-rouge&quot;&gt;font-size: calc(13px + 10vw)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Height-based media queries can be really useful: for example don’t necessarily set massive headings unless the height as well as the width is available&lt;/p&gt;

&lt;h2 id=&quot;vertical-rhythm&quot;&gt;Vertical rhythm&lt;/h2&gt;
&lt;p&gt;Rich sets vertical rhythm using margins, using &lt;code class=&quot;highlighter-rouge&quot;&gt;em&lt;/code&gt; units so it can scale appropriately.&lt;/p&gt;

&lt;h2 id=&quot;microtypography&quot;&gt;Microtypography&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;use correct punctuation symbols&lt;/li&gt;
  &lt;li&gt;em dash/en dash&lt;/li&gt;
  &lt;li&gt;hair/thin/normal space&lt;/li&gt;
  &lt;li&gt;kerning (on by default these days, w000t!)&lt;/li&gt;
  &lt;li&gt;treat numbers as ‘letters’ in running text to prevent them standing out and distracting the reader&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;numbers&quot;&gt;Numbers&lt;/h2&gt;
&lt;p&gt;Numerals are either ‘lining’, that are similar in treatment to uppercase letters, or ‘old style’ that reflect the style of lowercase letters. Both of these numerical styles may be set as either tabular (fixed width) or proportional (don’t line up).&lt;/p&gt;

&lt;p&gt;Recommended to use lining numerals in headings, and when all caps, otherwise use old style.&lt;/p&gt;

&lt;p&gt;Use tabular lining numerals in tables.&lt;/p&gt;

&lt;p&gt;If the font supports it, can use &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-numeric&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;font-variant-numeric&lt;/code&gt;&lt;/a&gt; CSS property to specify which numeric property/properties to use. The fallback for this is &lt;code class=&quot;highlighter-rouge&quot;&gt;font-feature-settings&lt;/code&gt;, but this resets everything and really is a spedgehammer/nut situation, and not sure it’s worth it. Might be better to just use &lt;code class=&quot;highlighter-rouge&quot;&gt;font-variant-numeric&lt;/code&gt; as a progressive enhancement.&lt;/p&gt;

&lt;h2 id=&quot;tables&quot;&gt;Tables&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;they should be readable&lt;/li&gt;
  &lt;li&gt;they should support a sense of the data within so you “can understand it by its shape”.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Recommendations:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;left align text&lt;/li&gt;
  &lt;li&gt;right align numbers&lt;/li&gt;
  &lt;li&gt;align the column headings to the data they’re heading up&lt;/li&gt;
  &lt;li&gt;if left/right alignment is not appropriate, align to a decimal point, or another appropriate character [except… this can only be reliably done using &lt;code class=&quot;highlighter-rouge&quot;&gt;text-align: &quot;character&quot; center&lt;/code&gt;, but this is in CSS text module level 4, and as such has no browser support as yet].&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Allow horizontal scrolling, with e.g.&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;.tablewrap {
    max-width: 100%
    overflow-x: auto;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You could wrap parts of cell heading labels within span which is hidden for very narrow screens (only). e.g.&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/* css */
.u-hide-when-tiny {
  display: none;
}

@media screen and (min-width: 480px/*or whatever*/) {
  .u-hide-when-tiny {
  display: inline
  }
}

/* html */
&amp;lt;div&amp;gt;
  D&amp;lt;span class=&quot;u-hide-when-tiny&quot;&amp;gt;ou&amp;lt;/span&amp;gt;bl&amp;lt;span class=&quot;u-hide-when-tiny&quot;&amp;gt;e&amp;lt;/span&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;but you have to be able to predict and control the heading labels in order to use this technique.&lt;/p&gt;

&lt;h2 id=&quot;font-choice&quot;&gt;Font choice&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;is it suitable for the text?&lt;/li&gt;
  &lt;li&gt;does it contain the glyphs you’re likely to need?&lt;/li&gt;
  &lt;li&gt;does it offer the effects and features that you’re likely to need?&lt;/li&gt;
  &lt;li&gt;does it have enough weights and styles?&lt;/li&gt;
  &lt;li&gt;Is the spirit and character of the typeface consistent with its intended usage?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;opentype&quot;&gt;OpenType&lt;/h2&gt;
&lt;p&gt;One way to turn OpenType features on for a font is by specifying which &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/font-feature-settings&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;font-feature-settings&lt;/code&gt;&lt;/a&gt; are desired. For example &lt;code class=&quot;highlighter-rouge&quot;&gt;font-feature-settings: &quot;swsh&quot; 1;&lt;/code&gt; turns on swashes, if they are available in the font. Note that you should only set OpenType features using &lt;code class=&quot;highlighter-rouge&quot;&gt;font-feature-settings&lt;/code&gt; if there’s not a supported longhand property associated with the feature you want to use. For example don’t use it to set small caps, to do this you should use &lt;code class=&quot;highlighter-rouge&quot;&gt;font-variant-caps: all-small-caps;&lt;/code&gt; instead (see &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/font-feature-settings&quot;&gt;MDN&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;To discover what OpenType features are available in a font, use &lt;code class=&quot;highlighter-rouge&quot;&gt;https://wakamaifondue.com/&lt;/code&gt;. Incredibly useful resource.&lt;/p&gt;

&lt;p&gt;Side note: some font files have embedded Python code to handle the more complex logic required to determine some glyph substitutions.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;glyphhanger&lt;/code&gt; node module reports what unicode ranges are used on a website, and can provide some subsetting functionality.&lt;/p&gt;

&lt;p&gt;Interesting post on &lt;a href=&quot;https://michaeljherold.com/2015/05/04/creating-a-subset-font/&quot;&gt;creating a subset font&lt;/a&gt; with Python.&lt;/p&gt;

&lt;h2 id=&quot;variable-fonts&quot;&gt;Variable fonts&lt;/h2&gt;

&lt;p&gt;Quite new. When I played with them six months ago, they weren’t ready, but now they seem like they’re nearly there.&lt;/p&gt;

&lt;p&gt;Subsetting a variable font can cause problems, so don’t for now.&lt;/p&gt;

&lt;p&gt;A variable font is a font file which makes many more versions of the same glyph available, for an entire typeface. For example a traditional typeface may offer a selection of weights over several individual font files. A variable font is capable of offering all weights between 1 and 999 in one font file. Weight is just one axis, or dimension, of variation. There are five registered axes:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;weight&lt;/li&gt;
  &lt;li&gt;width&lt;/li&gt;
  &lt;li&gt;italics&lt;/li&gt;
  &lt;li&gt;slant&lt;/li&gt;
  &lt;li&gt;optical-size&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;controlled using the CSS properties &lt;code class=&quot;highlighter-rouge&quot;&gt;font-weight&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;font-stretch&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;font-style&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;optical-sizing&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There have been calls for more registered axes, but the the registered axes are backed by the OpenType spec and so it depends what happens in that.&lt;/p&gt;

&lt;p&gt;You can have non-registered axes in your variable font file.&lt;/p&gt;

&lt;p&gt;You can have other axes that affect a subset of the 5 registered axes.&lt;/p&gt;

&lt;p&gt;Each axis can be addressed by providing its 4-letter OpenType feature code to &lt;code class=&quot;highlighter-rouge&quot;&gt;font-variation-settings&lt;/code&gt;. The convention is to address non-standard axes in uppercase.&lt;/p&gt;

&lt;p&gt;In &lt;code class=&quot;highlighter-rouge&quot;&gt;@font-face&lt;/code&gt; blocks, &lt;code class=&quot;highlighter-rouge&quot;&gt;font-style&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;font-stretch&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;font-weight&lt;/code&gt; all default to &lt;code class=&quot;highlighter-rouge&quot;&gt;normal&lt;/code&gt;, so you might need to set these explicitly. They take the following respective ranges:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;oblique -90 to 90&lt;/li&gt;
  &lt;li&gt;50% to 200%&lt;/li&gt;
  &lt;li&gt;1 to 999&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They will also take the &lt;code class=&quot;highlighter-rouge&quot;&gt;auto&lt;/code&gt; keyword, but that’s not implemented yet.&lt;/p&gt;

&lt;p&gt;Variable font spec says you can declare them within &lt;code class=&quot;highlighter-rouge&quot;&gt;@font-face&lt;/code&gt; using  &lt;code class=&quot;highlighter-rouge&quot;&gt;format(woff2 supports variations)&lt;/code&gt;, but that’s not implemented yet. The workaround is to include feature queries checking support for an appropriate value of &lt;code class=&quot;highlighter-rouge&quot;&gt;font-variation-settings&lt;/code&gt;, and only load the variable font when support is available.&lt;/p&gt;

&lt;p&gt;Can use (responsibly) in responsive design: for example could use &lt;code class=&quot;highlighter-rouge&quot;&gt;font-stretch&lt;/code&gt; to introduce slight variations across breakpoints.&lt;/p&gt;

&lt;p&gt;File compression is good. Can see soon we might be loading one variable font to provide all weights and styles rather than a handult of different font files. Overall performance will be interesting to track.&lt;/p&gt;

&lt;p&gt;For more see &lt;a href=&quot;http://clagnut.com/blog/2390&quot;&gt;Rich’s post on using variable fonts&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Font foundries aren’t sure yet how to price variable fonts, which is one reason their availability isn’t as widespread yet as we might have hoped.&lt;/p&gt;

&lt;p&gt;Variable font resources:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://v-fonts.com/&quot;&gt;v-fonts&lt;/a&gt; “A simple resource for finding and trying variable fonts”&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.axis-praxis.org/&quot;&gt;AxisPraxis&lt;/a&gt; “for playing with OpenType Variable Fonts”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;General resources:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://wakamaifondue.com/&quot;&gt;https://wakamaifondue.com/&lt;/a&gt; Explore which OpenType features are available in a font file&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://fontsinuse.com&quot;&gt;https://fontsinuse.com&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.whatfontis.com/&quot;&gt;https://www.whatfontis.com/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://typ.io/&quot;&gt;https://typ.io/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.typewolf.com/&quot;&gt;https://www.typewolf.com/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.typeroom.eu/&quot;&gt;http://www.typeroom.eu/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.parachutefonts.com/&quot;&gt;https://www.parachutefonts.com/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://abookapart.com/products/flexible-typesetting&quot;&gt;https://abookapart.com/products/flexible-typesetting&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://abookapart.com/products/webfont-handbook&quot;&gt;https://abookapart.com/products/webfont-handbook&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.alibris.co.uk/Shaping-Text-Jan-Middendorp/book/25412024&quot;&gt;https://www.alibris.co.uk/Shaping-Text-Jan-Middendorp/book/25412024&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
        <pubDate>Tue, 25 Sep 2018 00:00:00 +0000</pubDate>
        <link>http://decodeuri.net/2018/09/25/typography-workshop-rich-rutter/</link>
        <guid isPermaLink="true">http://decodeuri.net/2018/09/25/typography-workshop-rich-rutter/</guid>
        
        
      </item>
    
      <item>
        <title>SmashingConf London 2018</title>
        <description>&lt;h1 id=&quot;preface&quot;&gt;Preface&lt;/h1&gt;
&lt;p&gt;Immediately below are a few key points distilled from my raw notes. Following these is a writeup of my raw notes: they’re an extremely raw, totally unproofed write up of my notes from SmashingConf London 2018. There will be typos, incomplete sentences, fragmentary notes, repetitions, and possibly contradictions. Some of it might be even incomprehensible out of context, (but at least this way you don’t have to try to read my handwriting). I’ll tidy these up over the next few weeks, but most the important thing is to make them available soonest, so here you are.&lt;/p&gt;

&lt;p&gt;We can do better.&lt;/p&gt;

&lt;p&gt;And we will!&lt;/p&gt;

&lt;p&gt;Soon…&lt;/p&gt;

&lt;h1 id=&quot;some-key-points&quot;&gt;Some key points&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;use Brotli compression&lt;/li&gt;
  &lt;li&gt;use HTTP/2&lt;/li&gt;
  &lt;li&gt;You can have impactful images with fewer bytes transferred by degrading the image quality but combining it with a background colour or gradient via &lt;code class=&quot;highlighter-rouge&quot;&gt;mix-blend-mode&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;filter()&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;make sure you can remove A/B testing quickly if it causes performance problems&lt;/li&gt;
  &lt;li&gt;flatten the dependency tree with client hints&lt;/li&gt;
  &lt;li&gt;consider using &lt;code class=&quot;highlighter-rouge&quot;&gt;font-display&lt;/code&gt; with &lt;code class=&quot;highlighter-rouge&quot;&gt;preload&lt;/code&gt; client hint as a progressive enhancement to improve font loading UX (for this and alternatives see &lt;a href=&quot;https://www.zachleat.com/web/comprehensive-webfonts/&quot;&gt;https://www.zachleat.com/web/comprehensive-webfonts/&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;a little care how you construct and manipulate js arrays can take advantage of V8 optimisations&lt;/li&gt;
  &lt;li&gt;only load the js you need, and delay non-essential scripts&lt;/li&gt;
  &lt;li&gt;may improve jank by using &lt;code class=&quot;highlighter-rouge&quot;&gt;will-change&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;use &lt;code class=&quot;highlighter-rouge&quot;&gt;requestAnimationFrame&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Chrome User Experience Report provides real user metrics at scale (for Chrome)&lt;/li&gt;
  &lt;li&gt;Case studies of business cases for demonstrating the impact of web performance optimisation on business metrics are at &lt;a href=&quot;https://wpostats.com&quot;&gt;WPOStats&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;CSS grid is awesome&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;vitaly-new-front-end-adventures-in-responsive-design&quot;&gt;Vitaly: New Front-End Adventures in Responsive Design&lt;/h1&gt;

&lt;p&gt;Smashing: annual drop of 50% revenue; 66% users using ad blockers.&lt;/p&gt;

&lt;p&gt;copy docs - method to build a site with a text-first approach.&lt;/p&gt;

&lt;p&gt;Maslow for sites (bottom to top): speed &amp;gt; access &amp;gt; scale &amp;gt; style&lt;/p&gt;

&lt;p&gt;JAM Stack: JavaScript, API &amp;amp; markup&lt;/p&gt;

&lt;p&gt;Otto.de: German retailer uses vertical slicing of responsibilities: e.g. the breadcrumb team.&lt;/p&gt;

&lt;p&gt;AirBnB: ‘air/shots’: search engine for style guide that works for both designers and developers. Now extended to use machine learning to recognise their UI patterns&lt;/p&gt;

&lt;h2 id=&quot;sketch-related&quot;&gt;Sketch-related&lt;/h2&gt;
&lt;p&gt;Sketch to React tool: build mock-ups in React &amp;amp; then import into&lt;/p&gt;

&lt;p&gt;html-sketch-app  &lt;br /&gt;
nodeToSketchLayers
SymbolMaster&lt;/p&gt;

&lt;p&gt;Supernova Studio&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;define component root sizes in rem, but internal component sizes in em. Usual caution applies. [How might this blow up?]&lt;/li&gt;
  &lt;li&gt;plot font size against viewport width, and code the curve: for font-size see Mike Reithmueller. Could apply same principle to e.g. line-height&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;grid&quot;&gt;Grid&lt;/h2&gt;
&lt;p&gt;vw doesn’t take into account the width of the scrollbar.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;-start&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;-end&lt;/code&gt; are magic suffixes to grid line names…&lt;/p&gt;

&lt;!-- Beginnings of play: https://codepen.io/davidcmoulton/pen/qxaBmp --&gt;

&lt;p&gt;Can use for baseline grid - see https://codepen.io/rwdworkshop/pen/qVzyej&lt;/p&gt;

&lt;p&gt;Watch out for Edge &amp;lt; 16 implementation: can use &lt;code class=&quot;highlighter-rouge&quot;&gt;@supports (grid-gap: 0)&lt;/code&gt; to screen out Edge as it doesn’t support &lt;code class=&quot;highlighter-rouge&quot;&gt;grid-gap&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Grid bugs and their amelioration: https://github.com/rachelandrew/gridbugs&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://cssgridgarden.com&quot;&gt;cssgridgarden.com&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;text&quot;&gt;Text&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;zlib preset quality settings: slow compression, smaller size; faster compression, larger size&lt;/li&gt;
  &lt;li&gt;could use zopfli: improved gzip: good but slow, backwards compatible&lt;/li&gt;
  &lt;li&gt;brotli: better compression but slower (decompression speed on client is okay), and not backwards compatible: could use brotli with a gzip fallback. Requires HTTPS.
    &lt;ul&gt;
      &lt;li&gt;speed could be an issue?&lt;/li&gt;
      &lt;li&gt;check slides for details&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;images&quot;&gt;Images&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;large image with drop shadow: embed jpeg of big image into svg container, that also has embedded withing it a png that contains the dropshadow.&lt;/li&gt;
  &lt;li&gt;contrast swap technique (but bad for saving image)&lt;/li&gt;
  &lt;li&gt;could have large, highly compressed image displayed at a small size: file size could be a lot smaller than an smaller image of higher quality (bad for memory)&lt;/li&gt;
  &lt;li&gt;could blur unimportant bits of an image to reduce file size&lt;/li&gt;
  &lt;li&gt;try modifying default scan level for progressive jpegs in order to ‘ship fast and show soon’
    &lt;ul&gt;
      &lt;li&gt;mights try mozjpeg or adapt jpeg, or tinyJpeg, or Guetzli&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;letsenhance.io upscales images with machine learning&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;webfonts&quot;&gt;Webfonts&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;can use bulletproof@font-face syntax&lt;/li&gt;
  &lt;li&gt;can drop eot &amp;amp; opentype if don’t care about IE9 &amp;amp; old Androids&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fonts only downloaded when they’re references in css (after construction of DOM and CSSOM)
Flash of invisible text with 3 s timeout in FF &amp;amp; Chrome before displaying fallback, but Safari has no timeout!
Native browser API (web font loader)&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.zachleat.com/web/comprehensive-webfonts/&quot;&gt;“Comprehensive guide to font loading strategy”&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Critical FOFT&lt;/p&gt;

&lt;p&gt;Can store font in ServiceWorker cache.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;font-display&lt;/code&gt;&lt;/a&gt; (&lt;code class=&quot;highlighter-rouge&quot;&gt;optional&lt;/code&gt; could be a good bet).&lt;/p&gt;

&lt;p&gt;Web fonts often drop out of the HTTP cache because they have a low priority: Facebook 2015 study: 40% of the time, users don’t have the assets in the cache you’d expect. That’s pretty unreliable, so use ServiceWorker cache instead.&lt;/p&gt;

&lt;p&gt;Can use &lt;code class=&quot;highlighter-rouge&quot;&gt;unicode-range&lt;/code&gt; in &lt;code class=&quot;highlighter-rouge&quot;&gt;@font-face&lt;/code&gt;: good for internationalisation: only requests font if the page contains characters from that range. [Could this be automated?]&lt;/p&gt;

&lt;p&gt;Variable fonts (see &lt;code class=&quot;highlighter-rouge&quot;&gt;font-variation-settings&lt;/code&gt;: can only be targeted with media query and JavaScript (?as opposed to what?). Designers can add custom variable axes, in addition to the preregistered ones): not so much use for latin character sets, but in languages with large character sets, e.g. Japanese, it’s prohibitive to load the bold font weight as well as the regular one, so using variable fonts can help here. Poor browser support, but support is coming. Not many fonts support it yet, but type designers are on it now. &lt;code class=&quot;highlighter-rouge&quot;&gt;font-variation-settings&lt;/code&gt; is low level (a la Houdini), and so can override other font settings, e.g. &lt;code class=&quot;highlighter-rouge&quot;&gt;font-weight&lt;/code&gt;.
Variable fonts are incompatible with parametric fonts.
&lt;a href=&quot;https://axis-praxis.org&quot;&gt;axis-praxis.org&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;3rd-parties&quot;&gt;3rd parties&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;generate request maps for what&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://requestmap.webperf.tools&quot;&gt;requestmap.webperf.tools&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;WebpageTest black hole endpoint&lt;/li&gt;
  &lt;li&gt;could return an empty response from ServiceWorker if script doesn’t return in a set amount of time&lt;/li&gt;
  &lt;li&gt;sandbox property&lt;/li&gt;
  &lt;li&gt;SafeFrame?&lt;/li&gt;
  &lt;li&gt;IntersectionObserver: one of the family of &lt;code class=&quot;highlighter-rouge&quot;&gt;Observer&lt;/code&gt; APIs. Could investigate &lt;code class=&quot;highlighter-rouge&quot;&gt;ResizeObserver&lt;/code&gt; for element query prollyfill?&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;contain&lt;/code&gt; css property&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;css-custom-properties&quot;&gt;CSS custom properties&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;@supports (--custom: property)&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;everything using a variable expression is recalculated when the value is changed&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;can be scoped: if you put it on the &lt;code class=&quot;highlighter-rouge&quot;&gt;:root&lt;/code&gt; then it’s global&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;the old Intrinsic ratio for videos (2009) can be updated to use css custom properties&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;performance&quot;&gt;Performance&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;cheap Android phones running Chrome pass all mustard cutting checks but have limited memory &amp;amp; CPU capability.&lt;/li&gt;
  &lt;li&gt;could try for Device memory API, and fall back to mustard cutting if that doesn’t work&lt;/li&gt;
  &lt;li&gt;Google suggesting Moto G4 as an average reference phone.&lt;/li&gt;
  &lt;li&gt;script parsing time vary so much between devices it’s insane.&lt;/li&gt;
  &lt;li&gt;90% sites sending 1MB js which takes about 4s to even just parse on a Moto G4&lt;/li&gt;
  &lt;li&gt;(sites only use 40% of the js they’re sent)&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;takes 5s to get interactive on 3G network with 400ms round trip time with just 170k for everything on critical load path&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;scout approach to deploying on H/1.1, avoids having to re-download html when assets change&lt;/li&gt;
  &lt;li&gt;H/2 can have many small files&lt;/li&gt;
  &lt;li&gt;comparing H/1.1 with H/2: with no packet loss H/2 is (much?) faster, but what about packet loss with H/2? It can bork downloads (~20% US traffic affected by traffic loss).&lt;/li&gt;
  &lt;li&gt;server push: good for first load, but server will always push them even when they’re in the browser cache (solved by cache-digest: coming, but it’s not ready yet).&lt;/li&gt;
  &lt;li&gt;still important to package with H/2 in order from dictionary reuse in the compression: e.g. 5-10 bundles&lt;/li&gt;
  &lt;li&gt;browsers not optimised for this yet, so there can be browser runtime costs of sending many files over H/2.&lt;/li&gt;
  &lt;li&gt;with H/2, can load individual files instead of inlining critical css&lt;/li&gt;
  &lt;li&gt;resource hints: &lt;code class=&quot;highlighter-rouge&quot;&gt;rel=&quot;prefetch&quot;&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;rel=&quot;preconnect&quot;&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;rel=&quot;dns-prefetch&quot;&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;rel=&quot;preload&quot;&lt;/code&gt;. &lt;code class=&quot;highlighter-rouge&quot;&gt;preload&lt;/code&gt; enables you to set the right resource priority for preloading assets. for fonts you need to specify &lt;code class=&quot;highlighter-rouge&quot;&gt;crossorigin&lt;/code&gt;. DO NOT USE the deprecated &lt;code class=&quot;highlighter-rouge&quot;&gt;prerender&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;can fetch js with &lt;code class=&quot;highlighter-rouge&quot;&gt;preload&lt;/code&gt; and then only execute it when you need it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;serviceworkers&quot;&gt;ServiceWorkers&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;they try to get html files from network first, then cache&lt;/li&gt;
  &lt;li&gt;for ‘files’ (assets, I assume), try cache first, then network&lt;/li&gt;
  &lt;li&gt;in both cases, show offline fallback page if both respective attempts fail.&lt;/li&gt;
  &lt;li&gt;Google’s ‘workbox’ (? https://developers.google.com/web/tools/workbox/ ?)&lt;/li&gt;
  &lt;li&gt;pragmatist guide to service worker https://github.com/lyzadanger/pragmatist-service-worker&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;links&quot;&gt;Links&lt;/h2&gt;
&lt;p&gt;Slides at &lt;a href=&quot;https://www.smashed.by/lnd18&quot;&gt;www.smashed.by/lnd18&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;responsivebreakpoints.com&lt;/li&gt;
  &lt;li&gt;letsenhance.io&lt;/li&gt;
  &lt;li&gt;https://www.zachleat.com/web/comprehensive-webfonts/&lt;/li&gt;
  &lt;li&gt;https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display&lt;/li&gt;
  &lt;li&gt;axis-praxis.org&lt;/li&gt;
  &lt;li&gt;requestmap.webperf.tools&lt;/li&gt;
  &lt;li&gt;ratiobuddy.com - intrinsic ratios for videos (old technique)&lt;/li&gt;
  &lt;li&gt;Vitaly’s performance checklist&lt;/li&gt;
  &lt;li&gt;https://github.com/lyzadanger/pragmatist-service-worker&lt;/li&gt;
  &lt;li&gt;https://developers.google.com/web/tools/workbox/ ???&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href=&quot;https://data-data.net&quot;&gt;data-data.net&lt;/a&gt;
&lt;a href=&quot;https://airbnb.design&quot;&gt;airbnb.design&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;explore&quot;&gt;Explore&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;css modules&lt;/li&gt;
  &lt;li&gt;Mike Reithmueller font-size&lt;/li&gt;
  &lt;li&gt;Firefox grid inspector&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;vmin&lt;/code&gt; etc&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;ch&lt;/code&gt; unit: width of &lt;code class=&quot;highlighter-rouge&quot;&gt;0&lt;/code&gt; character in current typeface - of particular use with monospace fonts&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://cssgridgarden.com&quot;&gt;cssgridgarden.com&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;brotli &amp;amp; fallbacks&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;font-display: optional;&lt;/code&gt;
&lt;!-- - WE CAN USE INTERSECTIONOBSERVER WITH HYPOTHESIS! Also for lazy-loading our figures: this could --&gt;&lt;/li&gt;
  &lt;li&gt;Google’s idea for Moto G4 as a reference phone&lt;/li&gt;
  &lt;li&gt;browser calories extensions&lt;/li&gt;
&lt;/ul&gt;

&lt;!-- 
## Thoughts
- we need to get the pattern-library scaleable: export Nick's design system knowledge into the pattern library.
--&gt;

&lt;h1 id=&quot;phil-hawsksworth-making-platforms-and-processes-promote-performance&quot;&gt;Phil Hawsksworth: Making Platforms and Processes Promote Performance&lt;/h1&gt;

&lt;p&gt;Deployment:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;version control deployments&lt;/li&gt;
  &lt;li&gt;Avoid human interventions&lt;/li&gt;
  &lt;li&gt;Make them atomic&lt;/li&gt;
  &lt;li&gt;could create a URL for every version ready for circulation stakeholders’ approval&lt;/li&gt;
  &lt;li&gt;decide when and what to version (= a deployment)&lt;/li&gt;
  &lt;li&gt;script them&lt;/li&gt;
  &lt;li&gt;automate them&lt;/li&gt;
  &lt;li&gt;make it real: actual production deployments, not just to a pseudo-identical staging environment&lt;/li&gt;
  &lt;li&gt;make it first: work out how you’re going to deploy early in the project process&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;look-more-into&quot;&gt;Look more into&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;Book: Designing for performance: Laura Hogan&lt;/li&gt;
  &lt;li&gt;jamstack.org&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;rachel-andrew-into-the-weeds-of-css-layout&quot;&gt;Rachel Andrew: into the weeds of CSS layout&lt;/h1&gt;
&lt;p&gt;Mainly grids: not too many notes here as will be attending her workshop.&lt;/p&gt;

&lt;p&gt;Grid level 2 Working Draft shipped 6th Feb: includes subgrids!&lt;/p&gt;

&lt;p&gt;Sizing is often misunderstood in grid, a la flexbox: “how big is that box?”&lt;/p&gt;

&lt;p&gt;Sizes can be fixed (px, % etc), intrinsic (auto, fit-content, min-content, max-content) or flexible (fr)&lt;/p&gt;

&lt;p&gt;For grid track sizing:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;auto: generally fits without overflow, intrinsically has effect of &lt;code class=&quot;highlighter-rouge&quot;&gt;justify-content: stretch&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;min-content: uses all soft wraps without breaking out of its container&lt;/li&gt;
  &lt;li&gt;max-content: no soft wrapping, may overflow&lt;/li&gt;
  &lt;li&gt;fit-content(x): acts as max-content until it hits with x&lt;/li&gt;
  &lt;li&gt;fr uses available space&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;minmax() can set both min and max width for a grid track.
1fr track size is actually shorthand for minmax(auto, 1fr). This may not give equal track sizes if the width of the content under auto rules would be larger than 1fr.
If you want to force equal track sizes, risking overflow, use minmax(0, 1fr)&lt;/p&gt;

&lt;p&gt;Perf studies indicate that whatever you do with grid, it performs pretty much the same.&lt;/p&gt;

&lt;p&gt;[UC Browser has ~30% market share in India.]&lt;/p&gt;

&lt;p&gt;[Shapes is ready]&lt;/p&gt;

&lt;p&gt;“I’m not here to build shiny things for rich people. I never have been.”&lt;/p&gt;

&lt;p&gt;Grid gaps and tracks should be animatable (only implemented in FF atm)&lt;/p&gt;

&lt;p&gt;Suggest don’t use progressive enhancement approach for building a grid:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;build good document structure&lt;/li&gt;
  &lt;li&gt;build grid that you want&lt;/li&gt;
  &lt;li&gt;work out how to give non-implementing clients a good user experience
Using this approach means you’re not constrained by the limits of only what was possible before grid&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;una-kravets-and-martin-splitt-beyond-the-basics-of-image-optimisation&quot;&gt;Una Kravets and Martin Splitt: Beyond the basics of image optimisation&lt;/h1&gt;
&lt;p&gt;@una; @g33konaught&lt;/p&gt;

&lt;p&gt;WebP may be lossy or non-lossy (configuration).&lt;/p&gt;

&lt;p&gt;Questions for us:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Are our WebPs lossy?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Various optimisers:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;mozjpeg&lt;/li&gt;
  &lt;li&gt;Optipng&lt;/li&gt;
  &lt;li&gt;img loader for webpack&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lifecycle of an image load:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;download image&lt;/li&gt;
  &lt;li&gt;read header (setup)&lt;/li&gt;
  &lt;li&gt;decode image&lt;/li&gt;
  &lt;li&gt;VRAM upload&lt;/li&gt;
  &lt;li&gt;Composite&lt;/li&gt;
  &lt;li&gt;Display&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;jpg compresses in 8x8 pixel blocks.
Large areas of block colour compress better when using &lt;em&gt;lossless&lt;/em&gt; compression&lt;/p&gt;

&lt;p&gt;PNG header: first 4 bytes identifies a png file to the browser&lt;/p&gt;

&lt;p&gt;compositing is running shaders with all layers as input (Martin coding shaders in GLS language)&lt;/p&gt;

&lt;h2 id=&quot;techniques&quot;&gt;Techniques:&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;“blur up”: load tiny, scaled up image first to give an impression of the image while the main image loads.&lt;/li&gt;
  &lt;li&gt;manipulate the colour histogram e.g. make the image greyscale. Put it over a background colour or a gradient background (either of its own element, or of a (pseudo, maybe) element positioned behind it) then apply css filters/mix blend modes etc to the image element so it interacts with the background colour in funky ways to give coloured effects.&lt;/li&gt;
  &lt;li&gt;When SVG is used as a background image, you can’t affect it directly, but you can affect it with CSS filters.&lt;/li&gt;
  &lt;li&gt;“contrast swap”: reduce image contrast using linear transform function in an image editor to reduce the image file size, serve image, in CSS apply contrast &lt;code class=&quot;highlighter-rouge&quot;&gt;filter&lt;/code&gt; to make up for the contrast removal. Downside is downloading the image gives you the low contrast image version&lt;/li&gt;
  &lt;li&gt;never use gifs: send video instead&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Blend modes are either on or off, but filters are animatable. Blend modes’ hue, saturation, luminosity and colour use the Munsell colour system.&lt;/p&gt;

&lt;p&gt;Look into client hints to try to work out what quality image to send.&lt;/p&gt;

&lt;h1 id=&quot;andy-davies-ab-testing-ads-and-other-third-party-tags&quot;&gt;Andy Davies: “A/B testing, ads and other third party tags”&lt;/h1&gt;

&lt;p&gt;slideshare.net/andydavies&lt;/p&gt;

&lt;p&gt;3rd party: something you have on your page whose infrastructure and code is controlled by someone else.&lt;/p&gt;

&lt;p&gt;150 3rd parties in 2011; 5000+ in 2017.&lt;/p&gt;

&lt;p&gt;Chrome and Safari decode images on the main thread, so blocking js will block image display.&lt;/p&gt;

&lt;p&gt;Retailer removed Bazaar Voice from their site, gained a 4s speed reduction in Android, resulting in 26% increased revenue from that platform&lt;/p&gt;

&lt;p&gt;Safari double keys its cache for privacy reasons, which means loading a 3rd party library from a URL on site A means that its cache entry can’t be reused on site B.&lt;/p&gt;

&lt;p&gt;Optimizely blocks the critical render path for 2s. So:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;only have the experiments that you actually want to run&lt;/li&gt;
  &lt;li&gt;strip out jQuery if it’s already on the page&lt;/li&gt;
  &lt;li&gt;use separate tags for staging and production&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;long task API is coming, but it’s not here yet: https://www.w3.org/TR/longtasks/&lt;/p&gt;

&lt;p&gt;Make sure tests are testing the same things in the wild, e.g. if A/B testing images, make sure the images have a comparable file size.&lt;/p&gt;

&lt;p&gt;Do A/B testing on the CDN, not on the client. Fastly recognise this.&lt;/p&gt;

&lt;p&gt;Make sure you can always turn off A/B testing quickly in an emergency. Recounted one client who was A/B testing login buttons. A/B testing caused a massive slow down, but they couldn’t turn it off without removing the login button from their site entirely.
Some 3rd parties (ad providers tealeaf &amp;amp; Oracle were the examples), add a &lt;code class=&quot;highlighter-rouge&quot;&gt;beforeUnload&lt;/code&gt; handler: they want to finalise data or whatever before the next page load (they use this event because there’s no guarantee that the &lt;code class=&quot;highlighter-rouge&quot;&gt;unload&lt;/code&gt; event will ever fire). This can introduce a 1-2s delay when leaving a page with these ads on.&lt;/p&gt;

&lt;p&gt;Double check DevTools waterfall in WebPageTest, as it can be hard to see what’s going on. Example of game.co.uk: during page load, the browser had initiated 61 image requests before requesting the actual page [wtf?]. Couldn’t tell in DevTools, but waterfall chart in webpagetest made it clear.&lt;/p&gt;

&lt;p&gt;Average number of network requests sent by one ad is 56! One video ad can  use 3s CPU render time.&lt;/p&gt;

&lt;p&gt;He’s tried CSP and sub resource integrity to try to control rogue ads, but not had much success.&lt;/p&gt;

&lt;p&gt;RUM: Real user metrics rather than lab metrics (New Relic vs WebPageTest).&lt;/p&gt;

&lt;p&gt;Tag managers:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;too easy to add new tags&lt;/li&gt;
  &lt;li&gt;but it is easy to remove them, too (technically, if not politically)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Removing tags often political. Best scenarios when all parts of the business are aligned. Have an audit trail for what gets added, devs have permission to remove tags if they’re causing a performance problem.
Tag managers can help in controlling load order&lt;/p&gt;

&lt;p&gt;For each 3rd party you add, establish the value, and understand the cost.&lt;/p&gt;

&lt;h1 id=&quot;zach-leatherman-web-font-performance&quot;&gt;Zach Leatherman: Web font performance&lt;/h1&gt;

&lt;p&gt;slate.com accidentally announced that Mitt Romney was running for president when the actual story was that he’d decided
&lt;em&gt;not&lt;/em&gt; to run for president: this happened because an oblique webfont for the word “not” hadn’t loaded (FOIT).&lt;/p&gt;

&lt;p&gt;Browsers often hide content when loading web fonts (FOIT).&lt;/p&gt;

&lt;p&gt;Alternative is FOUT: the text appearing in its fallback font until the webfont loads. Much less serious than the old FOUC that we used to get while
waiting for CSS to download &amp;amp; be processed.&lt;/p&gt;

&lt;p&gt;Over the years, browsers have flipflopped between FOUT and FOIT (now with a 3s timeout at least).&lt;/p&gt;

&lt;p&gt;Play with the behaviour at https://www.zachleat.com/foitfout/&lt;/p&gt;

&lt;p&gt;FOIT repaints more than FOUT (although you can force a grouped repaint, but it’s not clear from &lt;code class=&quot;highlighter-rouge&quot;&gt;/foitfout&lt;/code&gt; what the tradeoffs are here with this)&lt;/p&gt;

&lt;p&gt;Don’t use bullet proof font face syntax any more&lt;/p&gt;

&lt;p&gt;Only need to use woff and woff2 formats these days&lt;/p&gt;

&lt;p&gt;Each webfont has its own independent loading cycle, which means independent FOITs.&lt;/p&gt;

&lt;p&gt;Whether and how FOIT / FOUT can be managed using &lt;code class=&quot;highlighter-rouge&quot;&gt;font-display&lt;/code&gt; as a progressive enhancement (only Chrome &amp;amp; FF atm): https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display Note this only changes how things display while loading, it doesn’t affect the load itself.&lt;/p&gt;

&lt;p&gt;Browsers use font-synthesis (fake bold/italic), when the real font version is not available. Useful for when fonts are loading, but don’t use this 
technique once font loading cycle has finished.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://filamentgroup.github.io/faux-pas/dist/demo.html&quot;&gt;faux-pas bookmarklet&lt;/a&gt; can identify occurrences of font-synthesis on a page&lt;/p&gt;

&lt;p&gt;The browser initiates a web font load when:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;CSS has been parsed and &lt;code class=&quot;highlighter-rouge&quot;&gt;@font-face&lt;/code&gt; found&lt;/li&gt;
  &lt;li&gt;a node has been found in the document:
    &lt;ul&gt;
      &lt;li&gt;that has an exact match on &lt;code class=&quot;highlighter-rouge&quot;&gt;font-family&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;has content&lt;/li&gt;
      &lt;li&gt;if using the &lt;code class=&quot;highlighter-rouge&quot;&gt;@font-face&lt;/code&gt;’s &lt;code class=&quot;highlighter-rouge&quot;&gt;unicode-range&lt;/code&gt;, content on the node matches&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because it takes inspection of the CSS to determine font(s) to download, the CSSOM can be completed, and render has got far enough along that the “paint text” step
has happened before the webfont is available. This is why and when the FOUT/FOIT occurs.&lt;/p&gt;

&lt;p&gt;Can use &lt;code class=&quot;highlighter-rouge&quot;&gt;preload&lt;/code&gt; with web fonts to reduce the elapsed time to font available; extra powerful when coupled with &lt;code class=&quot;highlighter-rouge&quot;&gt;display-font&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://drafts.csswg.org/css-font-loading/&quot;&gt;CSS Font Loading module&lt;/a&gt; (Editor’s Draft atm) may help in the future, Bram Stein tried to polyfill but it needs access to browser internals that just aren’t available, so he’s instead concentrated on &lt;a href=&quot;https://github.com/bramstein/fontfaceobserver&quot;&gt;Font Face Observer&lt;/a&gt;. It has no FOIT, forces one grouped repaint, and works with third party font hosts.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/zachleat/postcss-foft-classes&quot;&gt;postcss-foft-classes&lt;/a&gt; uses css classes to control font loading. Potentially powerful, but you need to be careful 
because once the appropriate css class is applied, the font is loaded whether there is any node using it or not.&lt;/p&gt;

&lt;h2 id=&quot;checklist&quot;&gt;Checklist:&lt;/h2&gt;

&lt;h3 id=&quot;no-invisible-text&quot;&gt;No invisible text:&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;use FOUT and font-synthesis&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;font-display&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;CSS font loading API&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;reflow-as-little-as-possible-as-soon-as-possible&quot;&gt;Reflow as little as possible, as soon as possible&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;group repaints so fewer  overall (CSS font loading API; variable fonts)&lt;/li&gt;
  &lt;li&gt;make font files smaller (&lt;code class=&quot;highlighter-rouge&quot;&gt;woff2&lt;/code&gt;, subsets)&lt;/li&gt;
  &lt;li&gt;trigger downloads sooner (&lt;code class=&quot;highlighter-rouge&quot;&gt;preload&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href=&quot;https://www.zachleat.com/web/comprehensive-webfonts/&quot;&gt;A comprehensive guide to font loading strategies&lt;/a&gt;&lt;/p&gt;

&lt;h1 id=&quot;patrick-meenhan-how-fast-is-it&quot;&gt;Patrick Meenhan: How fast is it?&lt;/h1&gt;

&lt;p&gt;Runs WebPageTest from his basement!&lt;/p&gt;

&lt;p&gt;There are more metrics than we know what to do with, so when selecting one, make sure it’s something that can be used to
improve the user experience.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;onload&lt;/code&gt; is easily gamed: think Twitter’s old client-side rendering.&lt;/p&gt;

&lt;h2 id=&quot;metric-recommendations&quot;&gt;Metric recommendations&lt;/h2&gt;
&lt;p&gt;Synthetic:
    - First (contentful) paint
    - Speed index
    - First interactive&lt;/p&gt;

&lt;p&gt;Real user measurement:
    - First (contentful) paint
    - First interactive&lt;/p&gt;

&lt;p&gt;User timing&lt;/p&gt;

&lt;p&gt;Pick some representative ‘profiles’:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;“My site isn’t that slow”&lt;/li&gt;
  &lt;li&gt;Chrome User Experience Report (CrUX) effective connection type&lt;/li&gt;
  &lt;li&gt;GA and RUM connection info&lt;/li&gt;
  &lt;li&gt;Slow users underrepresented: they do less on your site because your site is slow for them&lt;/li&gt;
  &lt;li&gt;Median &amp;amp; 99th percentile&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Socket connection time is a good proxy for user connection latency&lt;/p&gt;

&lt;h2 id=&quot;crux&quot;&gt;CrUX&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://developers.google.com/web/tools/chrome-user-experience-report/&quot;&gt;https://developers.google.com/web/tools/chrome-user-experience-report/&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Real user performance data from Chrome users&lt;/li&gt;
  &lt;li&gt;Aggregated per origin&lt;/li&gt;
  &lt;li&gt;Histogram of several metrics:
    &lt;ul&gt;
      &lt;li&gt;First paint&lt;/li&gt;
      &lt;li&gt;First contentful paint&lt;/li&gt;
      &lt;li&gt;DOM Content Loaded&lt;/li&gt;
      &lt;li&gt;Onload&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Split by:
    &lt;ul&gt;
      &lt;li&gt;Country&lt;/li&gt;
      &lt;li&gt;Effective connection type (2g, 3g, 4g…): describes how good the user’s connection &lt;em&gt;actually&lt;/em&gt; is, not what it nominally is&lt;/li&gt;
      &lt;li&gt;Device type (phone, tablet, desktop)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;[does HTTP/2 use the look ahead pre-parser? Not sure.]&lt;/p&gt;

&lt;p&gt;3rd parties break the HTTP/2 prioritisation strategy.&lt;/p&gt;

&lt;p&gt;TTFB: if this is long, nothing else matters.&lt;/p&gt;

&lt;p&gt;Server response time should measure if the server flushes early, so then can measure total time to deliver both header and full content&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;onload&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;fullyloaded&lt;/code&gt; events aren’t very useful.&lt;/p&gt;

&lt;p&gt;Look into &lt;a href=&quot;https://css-tricks.com/paint-timing-api/&quot;&gt;Paint Timing API&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When lazy loading images using IntersectionObserver, delay until first paint, but then load the images in order, don’t wait
until the container comes into view: phone networks will otherwise load the images too slowly &amp;amp; the user will notice it’s missing.&lt;/p&gt;

&lt;p&gt;[could be clever, loading the next one as its container gets close to the viewport, but is far enough away to allow time for the load to complete on a mobile network?…]&lt;/p&gt;

&lt;p&gt;Interactive metrics: first interactive vs consistently interactive. Showing lots before first interactive can be frustrating: you’re 
showing the user lots of lovely toys they can’t play with yet. Kind of a victim of own success in getting the time to first meaningful paint down so successfully&lt;/p&gt;

&lt;p&gt;iPhones have maintained lightening fast rendering: e.g. all JS &amp;amp; CSS [for what site?] downloaded at 3s desktop, 5s iPhone, low end 20s Android.&lt;/p&gt;

&lt;p&gt;user timing &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Performance/mark&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;performance.mark()&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Measure real user performance; evaluate that to develop improvements against it, testing using synthetic metrics (e.g. WebPageTest); deploy it and measure how (if)
it’s improved real user metrics (RUM).&lt;/p&gt;

&lt;p&gt;[WebPageTest: ‘custom metrics’ takes arbitrary js that runs once the page has loaded; ‘inject script’ runs the injected script while the page is loading]&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://wpostats.com/&quot;&gt;WPO Stats&lt;/a&gt; “Case studies and experiments demonstrating the impact of web performance optimization (WPO) on user experience and business metrics.”
Can submit to them as well as use their data.&lt;/p&gt;

&lt;p&gt;When emulating a less performant client (e.g. phone), make sure you throttle the CPU as well as the connection &amp;amp; using the viewport emulation.&lt;/p&gt;

&lt;p&gt;Re memory: you can test on a low-end 512Mb device to make sure things don’t blow up, but apart from that, let memory be the browser’s problem: don’t need to emulate memory.&lt;/p&gt;

&lt;p&gt;Speed Index (WebPageTest) vs Perceptual Speed Index (Lighthouse): perceptual speed index penalises when content moves around during loading (think ads, but also cookie popups).&lt;/p&gt;

&lt;p&gt;HTTP/2: don’t domain shard any more, serve everything from a single origin.&lt;/p&gt;

&lt;h1 id=&quot;umaar-hansa-devtools&quot;&gt;Umaar Hansa: DevTools&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;Performance panel: capture screenshots&lt;/li&gt;
  &lt;li&gt;local overrides: Override tab -&amp;gt; ‘enable local overrides’ -&amp;gt; add local override folder -&amp;gt; network tab (not panel): right click on resource: ‘Save for overrides’.
Notice a small purple dot now appears in the tab next to the filename indicating this file now overrides the file from the server. #everythingisawesome!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;render-performance&quot;&gt;Render performance&lt;/h2&gt;
&lt;p&gt;console popup tab (not main tab), ‘…’ -&amp;gt; performance monitor
console popup tab (not main tab), ‘…’ -&amp;gt; Rendering provides FPS metre, paint flashing, layer borders and scrolling performance issue indicators
console -&amp;gt; enable verbose logging will show best practice violations.
audits -&amp;gt; performance audit -&amp;gt; all_the_things!&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://developers.google.com/web/tools/lighthouse/&quot;&gt;https://developers.google.com/web/tools/lighthouse/&lt;/a&gt; has lots of best practice info.&lt;/p&gt;

&lt;h2 id=&quot;paint-indicators&quot;&gt;Paint indicators&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;performance.getEntriesByType('paint)&lt;/code&gt; gives access to &lt;code class=&quot;highlighter-rouge&quot;&gt;first-paint&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;first-contentful-paint&lt;/code&gt; in Chrome (FF returns empty array).&lt;/p&gt;

&lt;p&gt;console popup tab (not main tab), ‘…’ -&amp;gt; Coverage provides real time reports of unused CSS.&lt;/p&gt;

&lt;p&gt;Can programmatically access dev tools, so can script API via Puppeteer for automated tests&lt;/p&gt;

&lt;p&gt;Best way to know what’s happening in DevTools: read the codebase!&lt;/p&gt;

&lt;h1 id=&quot;ilya-grigorik-mystery-speaker&quot;&gt;Ilya Grigorik: Mystery speaker&lt;/h1&gt;

&lt;p&gt;Book: High performance browser networking&lt;/p&gt;

&lt;p&gt;How to measure UX on the web?&lt;/p&gt;

&lt;p&gt;As per a previous talk: there are many metrics out there, but which ones can you use to meaningfully measure the UX?&lt;/p&gt;

&lt;p&gt;Local lab/synthetic metrics can be got from WebPageTest/Lighthouse.
Small scale Real User Metrics can be gained from RUM tool used by the site.&lt;/p&gt;

&lt;p&gt;Large scale lab/synthetic metrics can be gained from HTTPArchive.&lt;/p&gt;

&lt;p&gt;Large scale RUM: Chrome User Experience Report (CrUX): provides UX metrics for how real world chrome users* experience the web&lt;/p&gt;

&lt;p&gt;*users who are syncing their browser history without a passphrase.&lt;/p&gt;

&lt;p&gt;Processing the data:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;anonymize&lt;/li&gt;
  &lt;li&gt;filter out non-public URLs&lt;/li&gt;
  &lt;li&gt;filter out low traffic URLs (so users can’t be identified by visits to these)&lt;/li&gt;
  &lt;li&gt;geocode by country and then by IP address&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Two ways of accessing the data:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Big Query: can query per domain&lt;/li&gt;
  &lt;li&gt;PageSpeed Insights: can query per URL (whether it’s your URL or not)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Network_Information_API&quot;&gt;Network Information API&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/igrigorik/netinfo-monitor&quot;&gt;Ilya’s netinfo-monitor&lt;/a&gt; reports network quality, as reported by the Network Information API.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.w3.org/TR/paint-timing/&quot;&gt;Paint Timing API&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Can use CrUX for competitor analysis, vertical benchmarking, monitor macro UX trends.&lt;/p&gt;

&lt;p&gt;Can use to calibrate lab tests with real world UX: used in PageSpeed.&lt;/p&gt;

&lt;p&gt;[Look into Airdroid]&lt;/p&gt;

&lt;p&gt;Chrome user selected data saver routes things via Google proxy to save on bandwidth. Uses HTTP header &lt;code class=&quot;highlighter-rouge&quot;&gt;Save-Data&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;WebPageTest             vs           CrUX
Emulated moto 4G                    Hundreds of different device types
3G throttling                       Full mix of Ethernet, WiFi, 4G, 3G, 2G…
Clean cache                         (HTTP, memory, network) cache
Index page only                     All pages
Deep traces &amp;amp; ‘00’s of metrics      Small set of diagnostic metrics&lt;/p&gt;

&lt;p&gt;Calibrate your lab against the RUM data for your site.&lt;/p&gt;

&lt;p&gt;CrUX:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;page load time: 3.4s&lt;/li&gt;
  &lt;li&gt;1st contentful paint: 1.4s&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Looks better than lab metrics (HTTPArchive).&lt;/p&gt;

&lt;h1 id=&quot;mathias-bynens-javascript-engine-internals&quot;&gt;Mathias Bynens: JavaScript Engine internals&lt;/h1&gt;

&lt;h2 id=&quot;element-kinds-in-v8&quot;&gt;Element kinds in V8&lt;/h2&gt;

&lt;p&gt;The internal type of the things held within an array.&lt;/p&gt;

&lt;p&gt;The more specific the elements kinds type, the more efficient the array operations.&lt;/p&gt;

&lt;p&gt;As the variation in the types of items held in an array becomes more heterogeneous, the elements kinds type of the array changes. It always changes in the direction specific -&amp;gt; generic, never in the other direction.&lt;/p&gt;

&lt;p&gt;For example: if an array has only small integer values, the array has a very specific elements kinds; once floating point numbers are added, the elements kinds becomes more generic, and if you add in some strings, the elements kinds becomes very generic. If the strings and floating point numbers are removed from the array, and only small integers remain, the elements kinds type remains very generic, because these values can never get more specific.&lt;/p&gt;

&lt;p&gt;A sparse array is always more generic than its equivalent packed array. This is because when trying to identify the type of an undefined element in a sparse array, JavaScript has to look all the way up the prototype chain before it can be sure it’s &lt;code class=&quot;highlighter-rouge&quot;&gt;undefined&lt;/code&gt;, and prototype chain lookup is expensive.&lt;/p&gt;

&lt;p&gt;The same lookup happens when addressing an array element that’s out of bounds, whether in a packed or a sparse array, so don’t do that!&lt;/p&gt;

&lt;p&gt;Try to avoid transitioning elements kinds. This has an effect on the array methods (except &lt;code class=&quot;highlighter-rouge&quot;&gt;find&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;findIndex&lt;/code&gt;, that are more expensive anyway [why?]).&lt;/p&gt;

&lt;p&gt;Use &lt;code class=&quot;highlighter-rouge&quot;&gt;for of&lt;/code&gt;: this works with &lt;code class=&quot;highlighter-rouge&quot;&gt;NodeList&lt;/code&gt;s as well as arrays, huzzah!&lt;/p&gt;

&lt;p&gt;Try to avoid having arrays containing &lt;code class=&quot;highlighter-rouge&quot;&gt;-0&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;NaN&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;Infinity&lt;/code&gt; [also &lt;code class=&quot;highlighter-rouge&quot;&gt;-Infinity&lt;/code&gt;?], because they cause elements kinds to transition downwards (more generic).&lt;/p&gt;

&lt;p&gt;Use &lt;code class=&quot;highlighter-rouge&quot;&gt;(...args)&lt;/code&gt; rest syntax for getting args into a proper array rather than the old &lt;code class=&quot;highlighter-rouge&quot;&gt;arguments&lt;/code&gt; array-like structure.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;d8&lt;/code&gt; is a REPL for &lt;code class=&quot;highlighter-rouge&quot;&gt;v8&lt;/code&gt;. See https://www.dropbox.com/s/h24711w7q5z5vfn/2018-02-08%2010.53.01.jpg?dl=0 for slide of how to run it (Note &lt;code class=&quot;highlighter-rouge&quot;&gt;%&lt;/code&gt;-prefixed items are not valid js names and so are deliberately used for V8 internals so they don’t accidentally get exposed.)&lt;/p&gt;

&lt;p&gt;Array constructor preallocated space, which might be more efficient when dealing with e.g. 9000+ elements, but the array it creates is sparse, so bear in mind what happens when trying to read from an unpopulated index. Alternatively, create the array using a primitive, and &lt;code class=&quot;highlighter-rouge&quot;&gt;push&lt;/code&gt; to it. Good for allocating 16 elements at a time, but may be slower than using  the array constructor for large arrays.&lt;/p&gt;

&lt;p&gt;Basically you’re either optimising array creation, or future array operations: you pays your money, you takes your choice.&lt;/p&gt;

&lt;p&gt;Arrays use Copy On Wrote (COW): if you have 10 copies of the same array, it’s only stored once, and all 10 references point to the same thing initially. Only when one of the 10 is modified is the array then copied and changed accordingly and the reference to the modified array is updated to point to the new (modified) copy. It’s a memory optimisation thing.&lt;/p&gt;

&lt;p&gt;Coming in ES2018: big ints, regex improvements.&lt;/p&gt;

&lt;h1 id=&quot;katie-hempenious-improving-page-performance-in-modern-web-apps&quot;&gt;Katie Hempenious: Improving page performance in modern web apps&lt;/h1&gt;

&lt;p&gt;Hardware and networks constrain performance: “you can’t escape physics”.&lt;/p&gt;

&lt;p&gt;Hardware constrains computationally expensive tasks, e.g. a radial gradient compared to solid colour.&lt;/p&gt;

&lt;p&gt;JavaScript code volume has a large impact on performance: parse/compile/execute, so remove unnecessary JavaScript.&lt;/p&gt;

&lt;p&gt;Strategies:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;remove unnecessary js&lt;/li&gt;
  &lt;li&gt;delay loading non-critical js&lt;/li&gt;
  &lt;li&gt;use another tool/context&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;remove-unnecessary-js&quot;&gt;Remove unnecessary js&lt;/h2&gt;
&lt;p&gt;Only use transpiled code where necessary (80% of browsers support ES2015).&lt;/p&gt;

&lt;p&gt;Use minifiers and optimisers. This can have tradeoffs: better compression may require more CPU/upfront work/possible side effects. Can reserve more aggressive optimisations for static resources that can be cached. Find the sweet spot between compression size and time.&lt;/p&gt;

&lt;p&gt;Tree-shaking (webpack, rollup etc.), made possible because ES2015 modules are static rather than dynamic. This is why exports are always top level.&lt;/p&gt;

&lt;p&gt;Webpack: typically used for frameworks: “static module bundler for modern JavaScript applications”. Features tree shaking; code splitting; hot module replacement and import of static assets.&lt;/p&gt;

&lt;p&gt;Rollup: typically used for libraries (e.g. used by React, Vue, Ember, D3, etc…). Features tree shaking only i.e. generates a smaller bundle, but lacks many of Webpack’s features.&lt;/p&gt;

&lt;p&gt;Tree shaking removes only unused exports, only supports 2015 modules; it may include more code than necessary (it defaults to safe i.e. includes the code if it’s not sure). Remove unused code yourself, because it’s hard to do automatically via static analysis because JavaScript is loosely typed.&lt;/p&gt;

&lt;h2 id=&quot;delay-js-load&quot;&gt;Delay js load&lt;/h2&gt;

&lt;p&gt;Defer non-essential scripts: prefer &lt;code class=&quot;highlighter-rouge&quot;&gt;defer&lt;/code&gt; over &lt;code class=&quot;highlighter-rouge&quot;&gt;async&lt;/code&gt;: &lt;code class=&quot;highlighter-rouge&quot;&gt;defer&lt;/code&gt; executes when the parser finishes parsing the document [ordering vs &lt;code class=&quot;highlighter-rouge&quot;&gt;async&lt;/code&gt;?].&lt;/p&gt;

&lt;p&gt;Use code-splitting and lazy-loading: it reduces js that needs to be parsed at startup, and reduces load of irrelevant code.&lt;/p&gt;

&lt;p&gt;Code splitting:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;1 application, 1 script: good compression, poor caching, poor granularity&lt;/li&gt;
  &lt;li&gt;1 module, 1 script: poor compression, good caching, good granularity&lt;/li&gt;
  &lt;li&gt;Goldilocks: bundles. The trick is to identify the level of granularity that works for you&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;use-another-tool-or-context&quot;&gt;Use another tool or context&lt;/h2&gt;

&lt;p&gt;Netflix reduced the Time To Interactive on their login page by 50% when they replaced React with vanilla js. The remainder of the app loads in the background while the user logs in.&lt;/p&gt;

&lt;p&gt;Moving things from the client to the server gives you less variation of metrics, and the server’s completely under your control.&lt;/p&gt;

&lt;h2 id=&quot;bandwidth-vs-latency&quot;&gt;Bandwidth vs latency&lt;/h2&gt;

&lt;p&gt;Increasing bandwidth has diminishing returns, bandwidth is sufficient in many markets. Average bandwidths by country (with corresponding bandwidth-only theoretical minimum load time of average sized 3.5Mbps web page, ignoring all latency):&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;UK: 26Mbps (0.13s)&lt;/li&gt;
  &lt;li&gt;Japan: 22Mbps (0.16s)&lt;/li&gt;
  &lt;li&gt;USA: 12Mbps (0.21s)&lt;/li&gt;
  &lt;li&gt;Brazil, Russia: 9Mbps (0.39s)&lt;/li&gt;
  &lt;li&gt;Indonesia: 5Mbps (0.70s)&lt;/li&gt;
  &lt;li&gt;India, Pakistan, Nigeria: 4Mbps (0.88s)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But latency is strongly correlated with performance:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;5G (spec): &amp;lt;= 4ms&lt;/li&gt;
  &lt;li&gt;4G: &amp;lt;100ms&lt;/li&gt;
  &lt;li&gt;3G: 100-500ms&lt;/li&gt;
  &lt;li&gt;2G: 300-1000ms&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sending more data is usually less expensive than setting up another connection [didn’t mention HTTP/2]. Fewer requests is better when latency is high, smaller file size is better when bandwidth is constrained.&lt;/p&gt;

&lt;p&gt;With HTTP/1.1 it takes 1-3 server round trips to download a tiny resource. TCP slow start limits the amount of data that can be sent at the beginning of a connection.&lt;/p&gt;

&lt;p&gt;Use caching: ideally determining freshness should not require a network request: use content-addressed URIs (e.g. logo[hash].jpg, not logo.jpg), in conjunction with max-age: [very large number]. Facebook quoted as saying this technique saved them 60% of requests.&lt;/p&gt;

&lt;p&gt;When BBC switched to ServiceWorkers they saw a 40% speed increase for high latency networks, and a 0-2% decrease in speed on high latency networks. It’s speculated that the performance drop on a low latency network was to do with the TLS handshake as HTTP/2 forces TLS.&lt;/p&gt;

&lt;h2 id=&quot;resource-prioritisation&quot;&gt;Resource prioritisation&lt;/h2&gt;

&lt;p&gt;Browsers prioritise loading of assets depending on whether they’re likely to be useful, and whether they’re render blocking:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Very high: Main resource (HTML); CSS (applicable media type)&lt;/li&gt;
  &lt;li&gt;High: JavaScript (synchronous)&lt;/li&gt;
  &lt;li&gt;Medium: JavaScript (synchronous); Images (in-viewport)&lt;/li&gt;
  &lt;li&gt;Low: JavaScript (async; deferred); Images (out-of-viewport)&lt;/li&gt;
  &lt;li&gt;Very low: CSS (non-applicable media type)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;dns-prefetch&lt;/p&gt;

&lt;p&gt;preconnect&lt;/p&gt;

&lt;p&gt;preload for &lt;em&gt;current&lt;/em&gt; navigation (has priority of the resource type being fetched) (very recent browser versions)&lt;/p&gt;

&lt;p&gt;prefetch for &lt;em&gt;next&lt;/em&gt; navigation (has the lowest possible priority) (not Safari)&lt;/p&gt;

&lt;p&gt;Consider a progressive enhancement (support not universal)&lt;/p&gt;

&lt;p&gt;(prerender and rel=”subresource” are deprecated).&lt;/p&gt;

&lt;p&gt;Ideal candidates for HTTP/2 push: critical resources that are used immediately, and that previously would have been inlined. It’s the quickest way to get resources to the browser, but weigh against that the lack of caching, pushing on subsequent page loads, and that it’s new tech (so may experience some wrinkles when using in anger). [Yoav talks more about this.]&lt;/p&gt;

&lt;p&gt;Use brotli for compression. Compared to gzip, you get a better compression ratio, so larger files will see a proportionally better improvement; faster decompression; range of compression speeds (but note that when selecting high compression it can be slower than gzip, use different levels of compression, and so speed of compression, depending on whether the item compressed is a static asset or dynamically generated at page request time).&lt;/p&gt;

&lt;p&gt;LinkedIn observed 20-30% reduction in file size vs gzip; Dropbox saw 20%.&lt;/p&gt;

&lt;p&gt;Implementing: enable it on server/CDN; no client config required: clients include &lt;code class=&quot;highlighter-rouge&quot;&gt;br&lt;/code&gt; in “Accept-Encoding” header if they can handle it; needs TLS; no issue if client doesn’t support it; supported in all major browsers.&lt;/p&gt;

&lt;h1 id=&quot;yoav-weiss-resource-loading-past-present-and-future&quot;&gt;Yoav Weiss: Resource loading: past, present and future&lt;/h1&gt;

&lt;p&gt;time != bytes/bandwidth because of latency. Connection to server is inherently latency-bound.&lt;/p&gt;

&lt;p&gt;Six areas that affect performance:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;handshake&lt;/li&gt;
  &lt;li&gt;TCP slow start&lt;/li&gt;
  &lt;li&gt;resource discovery&lt;/li&gt;
  &lt;li&gt;head of line problem&lt;/li&gt;
  &lt;li&gt;contention&lt;/li&gt;
  &lt;li&gt;bloat&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;TCP slow start: initial response is 10 packets which is equivalent to 14kb, response rate scales up exponentially from there when no packet loss. Try to get as much critical render stuff in the first 14k. [Does TCP slow start still apply with HTTP/2? Presumably, but can’t get resource on it].&lt;/p&gt;

&lt;p&gt;Browser ideal would be a flat dependency tree, but humans write deep, creating a deep dependency tree.&lt;/p&gt;

&lt;p&gt;HTTP/1.1 tries to avoid contention issues by delaying requests for low priority resources.&lt;/p&gt;

&lt;h2 id=&quot;http2&quot;&gt;HTTP/2&lt;/h2&gt;
&lt;p&gt;HTTP/2 helps sending the request, but can’t help with the server response: now download is bandwidth-bound, not latency bound.&lt;/p&gt;

&lt;p&gt;HTTP/2 server’s job is to send resources in correct prioritisation order, and is not very responsive to priority changes.&lt;/p&gt;

&lt;p&gt;HTTP/2 packet loss effectively reintroduces HTTP/1.1’s head of line problem, as the stream will stall until the missing TCP packet is resent.&lt;/p&gt;

&lt;h2 id=&quot;critical-rendering-path-resource-loading&quot;&gt;Critical rendering path: resource loading&lt;/h2&gt;
&lt;p&gt;The network imposes latency-, bandwidth-, and 3g/4g architecture constraints. Once things have begun to load it goes like this:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;dl html, discover css asap with look ahead pre-parser.&lt;/li&gt;
  &lt;li&gt;HTML -&amp;gt; DOM; CSS -&amp;gt; CSSOM; dl JavaScript&lt;/li&gt;
  &lt;li&gt;combine DOM/CSSOM/results of JavaScript execution into the render tree&lt;/li&gt;
  &lt;li&gt;layout&lt;/li&gt;
  &lt;li&gt;paint&lt;/li&gt;
  &lt;li&gt;composite&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Priority: HTML &amp;gt; CSS &amp;gt; JavaScript &amp;gt; Fonts &amp;gt; Images&lt;/p&gt;

&lt;p&gt;Cross resource compression (crossing the advantages of more bytes for greater compression with that of independent resources).&lt;/p&gt;

&lt;p&gt;“Web packaging” treats each file in a bundle separately, but they can be cached together.&lt;/p&gt;

&lt;p&gt;HTTP/2 compression dictionaries look promising, but there are security concerns.&lt;/p&gt;

&lt;p&gt;QUIC stack replaces TCP/TLS layer with the new QUIC protocol implemented in user space &lt;a href=&quot;https://www.chromium.org/quic&quot;&gt;https://www.chromium.org/quic&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;QUIC handles packet loss differently: rather than stalling all streams, it only stalls the stream that’s lost the packet.&lt;/p&gt;

&lt;p&gt;QUIC is released in 6-week cycles and has not stabilised, the IETF are involved, but it’s not ready for prime time yet (hopefully end of 2018).&lt;/p&gt;

&lt;p&gt;Early flushing isn’t always a good thing: for example, what happens if a database call fails, and you need to send a separate page, but you’ve already flushed the header of the page you were expecting to load before the db call failed? Its’ tricky.&lt;/p&gt;

&lt;p&gt;HTTP/2 push: server doesn’t know what’s currently in the browser cache. Can lead to a lot of unnecessary pushing. Could be solved by new proposals e.g. &lt;a href=&quot;https://calendar.perfplanet.com/2016/cache-digests-http2-server-push/&quot;&gt;cache-digests&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Can flatten the dependency tree with &lt;code class=&quot;highlighter-rouge&quot;&gt;preload&lt;/code&gt;: the resource priority depends on the value of the &lt;code class=&quot;highlighter-rouge&quot;&gt;as&lt;/code&gt; attribute. But &lt;code class=&quot;highlighter-rouge&quot;&gt;as&lt;/code&gt; is coarse, for example can’t specify &lt;code class=&quot;highlighter-rouge&quot;&gt;async&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;defer&lt;/code&gt;. Currently working on priority hints.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;preconnect&lt;/code&gt; hints for non-navigation requests to set up the connection early.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;connection coalescing&lt;/code&gt;:
TCP fast open + TLS 1.3
QUIC &amp;amp; IETF QUIC
Alt-Svc over DNS
[?]&lt;/p&gt;

&lt;p&gt;To reduce the effect of TCP slow start and contention, reduce the number of connections, and unshard your domains.&lt;/p&gt;

&lt;p&gt;“secondary certificates”: load only what you need.&lt;/p&gt;

&lt;p&gt;Brotli.&lt;/p&gt;

&lt;p&gt;Coming: compression API for browsers: compress data before sending it to the server. Respectful of the user, useful for RUM data &amp;amp; much more.&lt;/p&gt;

&lt;p&gt;Summary:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;HTTP/2&lt;/li&gt;
  &lt;li&gt;push, preload, preconnect&lt;/li&gt;
  &lt;li&gt;unshard domains, coalesce&lt;/li&gt;
  &lt;li&gt;load only what you need&lt;/li&gt;
  &lt;li&gt;Brotli&lt;/li&gt;
  &lt;li&gt;Future!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Future: device memory client hint + JavaScript API to try to identify low spec devices in order to send less code &amp;amp; smaller images.&lt;/p&gt;

&lt;p&gt;He’s writing a book on resource loading.&lt;/p&gt;

&lt;h1 id=&quot;emily-hayman-hitting-60-fps-every-time&quot;&gt;Emily Hayman: Hitting 60 fps every time&lt;/h1&gt;

&lt;p&gt;@eehayman Works at Algolia (search company)&lt;/p&gt;

&lt;p&gt;“Performant page load is just the prologue.”&lt;/p&gt;

&lt;p&gt;60 fps means one frame every 16.7ms.&lt;/p&gt;

&lt;p&gt;Beware of more frames: more frames means more processing which could lead to dropped frames and jank.&lt;/p&gt;

&lt;p&gt;Page render steps:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;calculate layout: happens on the CPU; calculates the page geometry; highly interdependent; recalculating layout is expensive&lt;/li&gt;
  &lt;li&gt;paint: happens on the CPU; calculation of visual styles; repaints only occur once per frame; repaints are expensive&lt;/li&gt;
  &lt;li&gt;composite: happens on the GPU; separates out compositor layers; allows for non-destructive changes i.e. no recalculation of layout nor repainting required.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Ideally, only change properties that trigger recompositing: transformations and opacity and that’s it!&lt;/p&gt;

&lt;p&gt;Can manually promote elements to their own compositing layer using the CSS property &lt;code class=&quot;highlighter-rouge&quot;&gt;will-change&lt;/code&gt;. Do this for things that are paint-expensive, fixed position and overflow scroll.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;will-change&lt;/code&gt; values:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;auto&lt;/code&gt;: behave as normal, don’t do anything special&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;scroll-position&lt;/code&gt;: element expected to animate or change its scroll position in the near future.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;contents&lt;/code&gt;: elements contents expected to animate or change in the near future.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;[css-property name]&lt;/code&gt;: indicates the property with the provided name is expected to change in the near future&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;[directions]&lt;/code&gt;:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/will-change&quot;&gt;https://developer.mozilla.org/en-US/docs/Web/CSS/will-change&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[MDN says not to Use &lt;code class=&quot;highlighter-rouge&quot;&gt;will-change&lt;/code&gt; to fix performance problems, not to prematurely optimise.]&lt;/p&gt;

&lt;p&gt;Too much of this gets resource intensive, so only use it when you need to.&lt;/p&gt;

&lt;p&gt;CSS animations: browser knows the end point of an animation so it can be optimised. CSS animations happen off the main thread so tend to generally be performant.&lt;/p&gt;

&lt;p&gt;Also see &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API&quot;&gt;Web Animations API&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;JavaScript animations are more finely tuned, and are capable of being made more responsive to the user; it runs on the main thread so risks dropping frames. If need to use JavaScript animation, use &lt;code class=&quot;highlighter-rouge&quot;&gt;RequestAnimationFrame&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To help prevent scroll jank, use passive event listeners where appropriate: &lt;a href=&quot;https://developers.google.com/web/updates/2016/06/passive-event-listeners&quot;&gt;https://developers.google.com/web/updates/2016/06/passive-event-listeners&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;IntersectionObserver.&lt;/p&gt;

&lt;p&gt;Avoid layout thrashing: read from the DOM and then write to the DOM, don’t try to do both at once.&lt;/p&gt;

&lt;p&gt;CSS containment: indicates an element subtree is independent from the rest of the document, it tells the browser it’s safe to optimise the element.&lt;/p&gt;

&lt;p&gt;test in DevTools: more tools -&amp;gt; rendering -&amp;gt; performance -&amp;gt; timeline.&lt;/p&gt;

&lt;h1 id=&quot;allison-mcknight-building-performance-for-the-long-term&quot;&gt;Allison McKnight: “Building performance for the long term”&lt;/h1&gt;

&lt;p&gt;Was on Etsy’s performance team with Lara Hogan.&lt;/p&gt;

&lt;p&gt;WebPageTest&lt;/p&gt;

&lt;p&gt;WPOStats&lt;/p&gt;

&lt;p&gt;Bring performance RUM into daily understanding.&lt;/p&gt;

&lt;p&gt;Consider factoring in performance data tracking into A/B testing. Etsy build ‘Sonic’ to report on how deployments change performance, using RUM with A/B testing.&lt;/p&gt;

&lt;p&gt;Internal Chrome extension for developers to run WebPageTest. Nice!&lt;/p&gt;

&lt;p&gt;Always evolve your metrics gathering and analysis: start with the most meaningful and take it from there. Iterate on how you integrate performance into workflows. Maintain expertise in performance. Celebrate performance!&lt;/p&gt;

&lt;p&gt;Use histograms and percentiles rather than averages.&lt;/p&gt;

&lt;h1 id=&quot;jake-archibald-in-the-loop&quot;&gt;Jake Archibald: “In the loop”&lt;/h1&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;requestAnimationFrame&lt;/code&gt; (rAF) happens before calculating style and performing layout and paint in Chrome &amp;amp; FF. Edge &amp;amp; Safari make rAF happen after layout and paint, but this is a bug.&lt;/p&gt;

&lt;p&gt;Compositor thread runs composition.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;MutationObserver&lt;/code&gt; (&amp;amp; other &lt;code class=&quot;highlighter-rouge&quot;&gt;Observer&lt;/code&gt;s) creates microtasks. Microtasks run when JavaScript finishes executing something. Promises also result in microtasks, so the promise callback will be at the bottom of the js callstack. Once the microtask queue begins to empty, it empties before any other JavaScript runs. Microtasks only run when the JavaScript stack is empty.&lt;/p&gt;

&lt;p&gt;Same domain iframes are on the same event loop as the main window.&lt;/p&gt;

&lt;p&gt;Cross domain iframes can’t be on the same event loop.&lt;/p&gt;

&lt;p&gt;When opening a page with target=”_blank” on the same domain, the new window has access to the parent window via &lt;code class=&quot;highlighter-rouge&quot;&gt;window.opener&lt;/code&gt;. Use &lt;code class=&quot;highlighter-rouge&quot;&gt;rel=&quot;noopener&quot;&lt;/code&gt; on all external links.&lt;/p&gt;

&lt;h1 id=&quot;css-layouts-rachel-andrew&quot;&gt;CSS layouts: Rachel Andrew&lt;/h1&gt;
&lt;p&gt;Original examples which I’ve then gone on to fork are at https://cssgrid.me/smashinglondon2018&lt;/p&gt;

&lt;h2 id=&quot;multicol&quot;&gt;multicol&lt;/h2&gt;
&lt;p&gt;multi-column layout reasonable fallback for grid in some cases.&lt;/p&gt;

&lt;p&gt;but multicol fragmentation: e.g. cards can break between image and following text&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;break-before&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;break-inside&lt;/code&gt; can be used to mitigate. E.g. can force no breaks after a heading.&lt;/p&gt;

&lt;p&gt;fragmentation a particular problem with printing layouts involving multi-col, grid &amp;amp; flexbox: use something else in a print stylesheet!&lt;/p&gt;

&lt;p&gt;e.g. use case: long sets of checkboxes&lt;/p&gt;

&lt;p&gt;use vertical media queries and use multicol within, in order to stop scrolling being required in a multicol environment&lt;/p&gt;

&lt;p&gt;gap property in grid and multicol is the same (coming to flexbox later, too)&lt;/p&gt;

&lt;p&gt;A lot of users of multicol are publishers: ebooks. CSS WG for multi-col is ~50% publishers using CSS to print books&lt;/p&gt;

&lt;h2 id=&quot;flexbox&quot;&gt;Flexbox&lt;/h2&gt;
&lt;p&gt;Flexbox or grid? If you’re putting widths on your flex items, you should probably be using grid.&lt;/p&gt;

&lt;p&gt;flexbox’s not wrapping by default is in sympathy with its single-dimensional nature.&lt;/p&gt;

&lt;p&gt;alignment started in flexbox level 1 (current level); later all alignment stuff (and gaps) put into box-alignment spec - look here for now on for flexbox alignment (updates to box-alignment won’t be ported back into flexbox);
grid uses box-alignment and gaps from box-alignment spec.&lt;/p&gt;

&lt;p&gt;align items sets as a group each flex item’s align-self property.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;auto&lt;/code&gt; never means default. Often ‘interesting’, and often not the initial value (that you might think). Make sure you know what it does.&lt;/p&gt;

&lt;p&gt;MDN docs often updated by spec authors and browser engineers.&lt;/p&gt;

&lt;p&gt;justify-content, not justify-items because you can’t justify one item, you have to justify a group ie the content of the flex container
    space-evenly (new? support?), gives an even measure on the 2 outsides, whereas space-around gives a half measure on the outsides.&lt;/p&gt;

&lt;p&gt;Grid probably fewer bugs in supporting browsers than flexbox, because grid happened all at once.&lt;/p&gt;

&lt;p&gt;[No one uses things between browser flags, Chrome origin trials: can opt your site into trialing new tech. Experiment to get devs using stuff &lt;em&gt;safely&lt;/em&gt;, early &amp;amp; so to provide feedback.&lt;/p&gt;

&lt;p&gt;Browser vendors don’t want to look bad, so they’re all keen to solve interoperability problems.]&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;align-content&lt;/code&gt; acts on the group of flex items as a whole (a la &lt;code class=&quot;highlighter-rouge&quot;&gt;justify-content&lt;/code&gt;) when you have wrapping items and there is space in the flex container. This is not the same as &lt;code class=&quot;highlighter-rouge&quot;&gt;align-items&lt;/code&gt;, which works on individual items within the container.&lt;/p&gt;

&lt;p&gt;Bear in mind not just &lt;code class=&quot;highlighter-rouge&quot;&gt;order&lt;/code&gt;, but also &lt;code class=&quot;highlighter-rouge&quot;&gt;direction&lt;/code&gt; imposes a &lt;em&gt;visual-only&lt;/em&gt; change in order wrt the DOM. Don’t do this with things that have logical order. Probably okay with other stuff. This also changes the order in which items are painted, which may or may not be desirable.&lt;/p&gt;

&lt;p&gt;flex-basis: auto - if width on an item, it’ll use that as the flex-basis: careful, this can catch you out!
          : content - the width of the content of the item(?) [less browser support]
          : 0 will mean all pixels will be distributed per grow/shrink factors&lt;/p&gt;

&lt;p&gt;can play with flex-basis to build components that don’t need media queries.&lt;/p&gt;

&lt;p&gt;flex-grow/shrink: factor affecting distribution of available space.&lt;/p&gt;

&lt;p&gt;A high flex-shrink value will make it get smaller, faster, than those with a larger number, but the browser won’t let the element disappear altogether, even if mathematically it should.&lt;/p&gt;

&lt;p&gt;Shorthand:  &lt;code class=&quot;highlighter-rouge&quot;&gt;flex-flow: [direction] [wrapping]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;flex: initial&lt;/code&gt; - default - can shrink but they don’t grow == &lt;code class=&quot;highlighter-rouge&quot;&gt;flex: 0 1 auto&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;flex: auto&lt;/code&gt; == &lt;code class=&quot;highlighter-rouge&quot;&gt;flex 1 1 auto&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;flex: none&lt;/code&gt; == &lt;code class=&quot;highlighter-rouge&quot;&gt;flex 0 0 auto&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;flex: 1&lt;/code&gt; == &lt;code class=&quot;highlighter-rouge&quot;&gt;flex 1 1 0&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;flex: 2&lt;/code&gt; == &lt;code class=&quot;highlighter-rouge&quot;&gt;flex 2 1 0&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Remember auto margins can be used to split items within a justified content block. An auto margin (everywhere, not just flexbox), use all available space it has access to, so putting it on one side forces it to the other side.&lt;/p&gt;

&lt;p&gt;Once things grow they will take up all available space so wont be able to use e.g. justify content, so if you want space between items, either apply a margin to the items, or constrain the widths (but if you’re constraining widths, should you be using grid instead?… (see above)).&lt;/p&gt;

&lt;p&gt;flexbugs&lt;/p&gt;

&lt;h2 id=&quot;grid-layout&quot;&gt;Grid layout&lt;/h2&gt;
&lt;p&gt;https://www.w3.org/TR/css-grid-1/
https://www.w3.org/TR/css-grid-2/&lt;/p&gt;

&lt;p&gt;Spec from IE team (IE10 &amp;amp; 11, can be used as a fallback. It’s very solid. ). Been around for ages but didn’t get very far for ages (b/c perf?).&lt;/p&gt;

&lt;p&gt;Bloomberg paid for the implementation for Blink and Webkit(?), implemented by a third party. Then FF did it, and Edge have moved from old MS grid to current W3C grid.&lt;/p&gt;

&lt;p&gt;Stable in current browsers (more so than flexbox).&lt;/p&gt;

&lt;p&gt;No subgrids yet.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;display: grid;
grid-template-columns: 150px 150px 300px;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;auto fills the tracks with content&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;grid-gap&lt;/code&gt; is shorthand for grid-row-gap &amp;amp; grid-column-gap. Will be transitioning to names row-gap and column-gap for better reuse. But mapping to new names from old will occur so won’t break.&lt;/p&gt;

&lt;p&gt;explicit grid: you define the grid template
implicit grid: content just slots it, you don’t specify all rows/columns for each piece of content
rows/columns autosize&lt;/p&gt;

&lt;p&gt;grid-auto-rows/columns sets the size of the row/column. auto works the same as flex-basis.&lt;/p&gt;

&lt;p&gt;% &amp;amp; length units work the same in grid/fb&lt;/p&gt;

&lt;p&gt;fr unit shares out the available space, not all the space (so not %).&lt;/p&gt;

&lt;p&gt;with grid, you apply things to the grid container, whereas with flexbox, the individual items broadly determine the spacing&lt;/p&gt;

&lt;p&gt;grid-template-columns etc define a ‘track listing’. Can use e.g. &lt;code class=&quot;highlighter-rouge&quot;&gt;repeat(3, 1fr);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;minmax()-assigned row/column sizing prevents overflow if more contents than expected.&lt;/p&gt;

&lt;p&gt;grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    auto-fill leaves spaces for missing tracks at the end
    auto-fit takes up all available space&lt;/p&gt;

&lt;p&gt;Unless you position things, grid will put content in the next available place on the grid&lt;/p&gt;

&lt;p&gt;No way to add rules, or colour cells in the grid spec per se. You need to do this via HTML. It may come via pseudoelements, but not yet.&lt;/p&gt;

&lt;p&gt;FF devtools good for layout (Chrome DevTools for performance).&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;grid-auto-flow: dense;&lt;/code&gt; backfills and may move things out of order. Do not use if the grid contains things with a logical order (but if just, say, a wall of images, then that’s okay). Looks a bit like masonry, but it’s not (masonry is awful for performance).&lt;/p&gt;

&lt;p&gt;placement:  grids are 1-indexed. can specify order with negative numbers for explicit but not implicit grid. default is 1&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;grid-column: 1 / 3&lt;/code&gt; is short for:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;grid-column-start: 1
grid-column-end: 3

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Placement targets the lines, not the tracks themselves, remember, e.g. a 3 track grid has 4 lines (see dev tools).&lt;/p&gt;

&lt;p&gt;Can name lines on the grid with strings in square brackets.&lt;/p&gt;

&lt;p&gt;lines can be named anything&lt;/p&gt;

&lt;p&gt;lines can have multiple names&lt;/p&gt;

&lt;p&gt;you can use any of a line’s names to address it.&lt;/p&gt;

&lt;!-- WOAH! https://codepen.io/davidcmoulton/pen/paevry?editors=1100 --&gt;

&lt;p&gt;If you want to line up grid components to line up with older %-based-laid-out components you can use %, probably the only good reason to though.&lt;/p&gt;

&lt;p&gt;Grid template areas: create a template and place things into it. Need to define a name for things on the grid with &lt;code class=&quot;highlighter-rouge&quot;&gt;grid-area&lt;/code&gt;
populated via &lt;code class=&quot;highlighter-rouge&quot;&gt;grid-template-areas&lt;/code&gt; 
&lt;!-- https://codepen.io/davidcmoulton/pen/YeZyqp?editors=1100 --&gt;
overall shape of area needs to be rectangular.
Each of the areas will yield line names e.g. ‘sidebar’ area will yield lines named ‘sidebar-start’ and ‘sidebar-end’.
A line may have several names, derived from the area names.&lt;/p&gt;

&lt;p&gt;grid areas are assigned without quotes, but references from grid-area-template within quotes. grid-template-area has one string per ‘row’&lt;/p&gt;

&lt;p&gt;You could overdo it tho’.&lt;/p&gt;

&lt;p&gt;Looks like this could be v useful in small ways, but need to take a lot of care reordering things so that they’re not inaccessible.&lt;/p&gt;

&lt;p&gt;Remember 1fr distributes available space, so doesn’t guarantee equal sizes. If you need equal sizes, use &lt;code class=&quot;highlighter-rouge&quot;&gt;minmax(0, 1fr)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;“I’ve seen some people who don’t understand how float based grid systems work because they’ve learned their css from Bootstrap” :-O&lt;/p&gt;

&lt;!-- 12 col grid system in css: https://codepen.io/davidcmoulton/pen/aqJdop?editors=1100 --&gt;

&lt;p&gt;Some browsers have clamped the max grid size to 1000 tracks, but there doesn’t seem to be a performance reason to do this,
so they remove that restriction. The spec leaves this as an implementation detail.&lt;/p&gt;

&lt;p&gt;Use grid for small, component use cases: doesn’t need to just be at page-level.&lt;/p&gt;

&lt;!-- `dl` laid out using grid https://codepen.io/davidcmoulton/pen/oEZbed?editors=1100 --&gt;

&lt;p&gt;Sizing, e.g. &lt;code class=&quot;highlighter-rouge&quot;&gt;minmax()&lt;/code&gt;
CSS intrinsic (the size its content makes it) &amp;amp; extrinsic (developer-specified size) sizing specification spec. For intrinsic track sizing, browser uses these to calculate sizes, they are also available to developers to use directly:
    - &lt;code class=&quot;highlighter-rouge&quot;&gt;min-content&lt;/code&gt;: track gets as small as it can, with softwrap &amp;amp; no oveflow (largest thing in the track sets the minimum size)
    - &lt;code class=&quot;highlighter-rouge&quot;&gt;max-content&lt;/code&gt;: may cause overflow
    - &lt;code class=&quot;highlighter-rouge&quot;&gt;fit-content([width])&lt;/code&gt;: acts like max content until it gets to [width] Very useful
    - &lt;code class=&quot;highlighter-rouge&quot;&gt;auto&lt;/code&gt;: by default it stretches (so if you don’t want it to stretch, need to set &lt;code class=&quot;highlighter-rouge&quot;&gt;justify-items&lt;/code&gt; to &lt;code class=&quot;highlighter-rouge&quot;&gt;start&lt;/code&gt;, for example.)&lt;/p&gt;

&lt;p&gt;Should get these sizing keywords into &lt;code class=&quot;highlighter-rouge&quot;&gt;flex-basis&lt;/code&gt; at some point.&lt;/p&gt;

&lt;p&gt;box alignment: start/end rather than flex-start/-end for both justify-content, align-content
  everything stretches with stretch, except if things have an intrinsic aspect ratio like images, videos and form elements(!).
  FF grid inspector is really useful for grokking what’s going on here. Try it out and play.
  align-self and justify-self (like flexbox).&lt;/p&gt;

&lt;p&gt;vertical % on gaps and on padding/margin of flexbox and grid: spec allows for ambiguity: different browsers implement it in different ways; spec will be changed, but for now don’t use % on vertical spacing and gaps, will probably give you 0 in FF.&lt;/p&gt;

&lt;p&gt;Browser support
Not supported by:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;UC browser (based on old version of Chrome)&lt;/li&gt;
  &lt;li&gt;other non-western mobile browsers
i.e. some current browsers, it’s not just old browsers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;IE10-11 has -ms-prefixed old IE style grid. No new vendor prefixes.&lt;/p&gt;

&lt;p&gt;Spec includes what happens to old css when turned into flex items/grid items which helps us tweak code for fallbacks, but without having to build 2 separate layouts.&lt;/p&gt;

&lt;p&gt;[Can use autoprefixer on CodePen.]&lt;/p&gt;

&lt;p&gt;float/clear applied to an element that also becomes a grid item is ignored (like in flexbox).&lt;/p&gt;

&lt;p&gt;could use &lt;code class=&quot;highlighter-rouge&quot;&gt;display: inline-block&lt;/code&gt; as a fallback. Can use &lt;code class=&quot;highlighter-rouge&quot;&gt;vertical-align&lt;/code&gt;. Both are ignored when it’s a grid item.&lt;/p&gt;

&lt;p&gt;spec says things are “blockified” before becoming grid items (i.e. no longer inline).&lt;/p&gt;

&lt;p&gt;fallback &lt;code class=&quot;highlighter-rouge&quot;&gt;display: table-cell&lt;/code&gt; Can use &lt;code class=&quot;highlighter-rouge&quot;&gt;vertical-align&lt;/code&gt;. Both are ignored when it’s a grid item. When it becomes a grid item, also throws away the anonymous boxes associated with &lt;code class=&quot;highlighter-rouge&quot;&gt;table-cell&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;fallback to multicol: multicol stuff is ignored when element becomes a grid item.&lt;/p&gt;

&lt;p&gt;So for fallbacks, this mainly leaves widths and whitespace: can use feature queries.&lt;/p&gt;

&lt;p&gt;can have multiple clauses in a feature query:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@supports ( (display: flex) and (display: grid) ) {
  ...
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Beware checking for lack of support, otherwise may not get the result you expect as feature queries not supported in any IE.&lt;/p&gt;

&lt;p&gt;Can reset width in a feature query for a grid item (or anything else), with &lt;code class=&quot;highlighter-rouge&quot;&gt;width: auto&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Can set &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;table&amp;gt;&lt;/code&gt; as a grid and make it more responsive. Will probably need subgrids to be really effective, but that could be great for us! (Level 2 is mainly subgrids.)&lt;/p&gt;

&lt;p&gt;Coming in later levels of the grid spec: aspect ratio stuff: now there are 2 dimensions, these things start to matter.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;display: contents&lt;/code&gt; removes everything to do with box generation for its element, replacing it with those of its children. Still exists, just some properties are removed.
Useful when semantically important but graphically null elements are used: e.g. a &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;ul&amp;gt;&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;fieldset&amp;gt;&lt;/code&gt;. This gets over some of the problems with flexbox and grid only acting on immediate children: you can effectively remove elements wrt style to make a grandchild part of a grid or flex layout.&lt;/p&gt;

&lt;p&gt;A block formatting context (BFC) contains floats, and can be thought of as a mini-layout. Can generate it with &lt;code class=&quot;highlighter-rouge&quot;&gt;overflow: auto&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;hidden&lt;/code&gt; in order to force creation of a BFC.
But should you? Probably not. Instead, new: &lt;code class=&quot;highlighter-rouge&quot;&gt;display: flow-root&lt;/code&gt;: all this does is create a new block formatting context.&lt;/p&gt;

&lt;p&gt;CSS Exclusions. Removed from CSS shapes. Implemented in IE and Edge: &lt;code class=&quot;highlighter-rouge&quot;&gt;-ms-wrap-flow: both&lt;/code&gt;. It allows text to span across an image:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;word1 word2 ---- word3 word4
word5 word6 | I |word7 word8
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;!-- TODO:
work on https://codepen.io/davidcmoulton/pen/eVvZOe?editors=1100 to get to https://s3-us-west-2.amazonaws.com/s.cdpn.io/12005/grid-task.png
--&gt;
</description>
        <pubDate>Tue, 13 Feb 2018 00:00:00 +0000</pubDate>
        <link>http://decodeuri.net/2018/02/13/smashing-conference-london-2018-initial-notes/</link>
        <guid isPermaLink="true">http://decodeuri.net/2018/02/13/smashing-conference-london-2018-initial-notes/</guid>
        
        
      </item>
    
      <item>
        <title>Building a pattern library for scholarly publishing</title>
        <description>&lt;p&gt;Describes building a pattern library implementing a design system for an open access science journal. The approach taken makes both the design system and the pattern library codebase highly flexible and maintainable. Part 1 of probably 2.&lt;/p&gt;

&lt;h2 class=&quot;no_toc&quot; id=&quot;contents&quot;&gt;Contents&lt;/h2&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#introduction&quot; id=&quot;markdown-toc-introduction&quot;&gt;Introduction&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#deciding-on-an-approach&quot; id=&quot;markdown-toc-deciding-on-an-approach&quot;&gt;Deciding on an approach&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#design-systems-and-atomic-design&quot; id=&quot;markdown-toc-design-systems-and-atomic-design&quot;&gt;Design systems and Atomic Design&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#patternlab&quot; id=&quot;markdown-toc-patternlab&quot;&gt;PatternLab&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#principles&quot; id=&quot;markdown-toc-principles&quot;&gt;Principles&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#identifying-and-naming-the-patterns&quot; id=&quot;markdown-toc-identifying-and-naming-the-patterns&quot;&gt;Identifying and naming the patterns&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#deciding-on-a-process&quot; id=&quot;markdown-toc-deciding-on-a-process&quot;&gt;Deciding on a process&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#tickets&quot; id=&quot;markdown-toc-tickets&quot;&gt;Tickets&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#board&quot; id=&quot;markdown-toc-board&quot;&gt;Board&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#code-management&quot; id=&quot;markdown-toc-code-management&quot;&gt;Code management&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#build&quot; id=&quot;markdown-toc-build&quot;&gt;Build&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#basic-build-pipeline&quot; id=&quot;markdown-toc-basic-build-pipeline&quot;&gt;Basic build pipeline&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#scss&quot; id=&quot;markdown-toc-scss&quot;&gt;SCSS&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#organising-the-typography&quot; id=&quot;markdown-toc-organising-the-typography&quot;&gt;Organising the typography&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#markup&quot; id=&quot;markdown-toc-markup&quot;&gt;Markup&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#images&quot; id=&quot;markdown-toc-images&quot;&gt;Images&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#extended-build-pipeline&quot; id=&quot;markdown-toc-extended-build-pipeline&quot;&gt;Extended build pipeline&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#pattern-behaviour-with-javascript&quot; id=&quot;markdown-toc-pattern-behaviour-with-javascript&quot;&gt;Pattern behaviour with JavaScript&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#javascript-testing&quot; id=&quot;markdown-toc-javascript-testing&quot;&gt;JavaScript testing&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#where-is-it-tho&quot; id=&quot;markdown-toc-where-is-it-tho&quot;&gt;Where &lt;em&gt;is it&lt;/em&gt; tho’?&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#lessons-learned&quot; id=&quot;markdown-toc-lessons-learned&quot;&gt;Lessons learned&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#in-conclusion&quot; id=&quot;markdown-toc-in-conclusion&quot;&gt;In conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;I recently had the privilege of being involved in the ground-up rebuild of an &lt;a href=&quot;https://elifesciences.org&quot;&gt;online science journal&lt;/a&gt;. The whole stack was rebuilt from scratch using a microservices approach. The journal is building a reputation for innovation in science publishing, and it was a great opportunity to get involved in a green field project to build best web practice into this arena.  In this post I’ll be focusing on how we built the front end. A companion post is planned about how we integrated the pattern library into the site.&lt;/p&gt;

&lt;p&gt;Note that the code examples have been simplified for clarity.&lt;/p&gt;

&lt;h2 id=&quot;deciding-on-an-approach&quot;&gt;Deciding on an approach&lt;/h2&gt;

&lt;h3 id=&quot;design-systems-and-atomic-design&quot;&gt;Design systems and Atomic Design&lt;/h3&gt;
&lt;p&gt;During the design phase, I had many constructive conversations with the designer, including prototyping some ideas to help decide on an overall approach to various things. He decided we needed a design system in order to retain both flexibility and design coherence not only for the initial build, but for what we might want to create in the future.&lt;/p&gt;

&lt;p&gt;Building a design system requires a modular, hierarchical approach, and this approach is well supported by using a pattern library. Brad Frost’s &lt;a href=&quot;http://bradfrost.com/blog/post/atomic-web-design/&quot;&gt;Atomic Design&lt;/a&gt; principles are a natural fit with the designer’s concept for the design system, and so we chose Atomic Design as the mental model for our new site design.&lt;/p&gt;

&lt;p&gt;Atomic Design considers reusable, composable design patterns in a hierarchy described in terms of &lt;code class=&quot;highlighter-rouge&quot;&gt;atoms&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;molecules&lt;/code&gt;, and &lt;code class=&quot;highlighter-rouge&quot;&gt;organisms&lt;/code&gt;. An &lt;code class=&quot;highlighter-rouge&quot;&gt;atom&lt;/code&gt; is the smallest unit of the design system, for example a button or a link. A more complex &lt;code class=&quot;highlighter-rouge&quot;&gt;molecule&lt;/code&gt; pattern may be composed by assembling a collection of &lt;code class=&quot;highlighter-rouge&quot;&gt;atom&lt;/code&gt;-level patterns, for example a teaser within a listing. An &lt;code class=&quot;highlighter-rouge&quot;&gt;organism&lt;/code&gt; is more complex again and may comprise a number of included &lt;code class=&quot;highlighter-rouge&quot;&gt;atoms&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;molecules&lt;/code&gt;. We discovered that it’s not really worth trying to impose a strict hierarchy to distinguish &lt;code class=&quot;highlighter-rouge&quot;&gt;molecules&lt;/code&gt; from &lt;code class=&quot;highlighter-rouge&quot;&gt;organisms&lt;/code&gt;. Whilst trying generally to maintain the distinction that &lt;code class=&quot;highlighter-rouge&quot;&gt;organisms&lt;/code&gt; are a higher-order pattern than &lt;code class=&quot;highlighter-rouge&quot;&gt;molecules&lt;/code&gt;, it’s okay for &lt;code class=&quot;highlighter-rouge&quot;&gt;molecules&lt;/code&gt; to contain other &lt;code class=&quot;highlighter-rouge&quot;&gt;molecules&lt;/code&gt; as well as &lt;code class=&quot;highlighter-rouge&quot;&gt;atoms&lt;/code&gt;, and for &lt;code class=&quot;highlighter-rouge&quot;&gt;organisms&lt;/code&gt; to contain &lt;code class=&quot;highlighter-rouge&quot;&gt;organisms&lt;/code&gt; as well as lower-order patterns. With only 3 hierarchy levels to play with, we found we got most benefit from a pragmatic interpretation of the Atomic Design hierarchy.&lt;/p&gt;

&lt;h3 id=&quot;patternlab&quot;&gt;PatternLab&lt;/h3&gt;
&lt;p&gt;Having decided on Atomic Design, we chose Brad Frost’s &lt;a href=&quot;http://patternlab.io/&quot;&gt;PatternLab&lt;/a&gt; as the natural tool to deliver it. PatternLab uses &lt;a href=&quot;http://mustache.github.io/&quot;&gt;mustache templating&lt;/a&gt; and provides a web interface to display the patterns next to the markup that defines them, along with any optional annotations you may wish to supply. Since we started the project, other pattern library candidates have appeared that may have served just as well, for example &lt;a href=&quot;https://fractal.build/&quot;&gt;Fractal&lt;/a&gt;, but they weren’t available then; PatternLab was the the best available tool at the time, and it has served us well.&lt;/p&gt;

&lt;p&gt;Useful abilities of PatternLab include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Can view the template code and the compiled HTML next to its pattern.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Can annotate a pattern with style-guide level information.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Pattern search.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Option to view any PatternLab page without the PatternLab UI in case it’s getting in the way.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Can break down Atomic Design levels to group patterns of a particular type within a level. This can make it easier to track down a pattern on the file system; for example, the &lt;code class=&quot;highlighter-rouge&quot;&gt;molecules&lt;/code&gt; patterns might be grouped like this:&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;molecules
├── general
│   ├── ...
│   └── ... 
├── navigation
│   ├── ...
│   └── ... 
└── teasers
    ├── ...
    └── ...  
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;The display can be restricted to show any level of pattern grouping, and only that level e.g. just the &lt;code class=&quot;highlighter-rouge&quot;&gt;atoms&lt;/code&gt; or just the navigation &lt;code class=&quot;highlighter-rouge&quot;&gt;molecules&lt;/code&gt; (see above diagram). This is useful when trying to see how different patterns within a group behave at breakpoints, to iron out inconsistencies.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Set the effective viewport width in px or ems to see how patterns behave in that situation.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;More general one-click buttons to set a general viewport width.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;DISCO MODE! i.e. constant automatic changing of the viewport to random widths to see what breaks (music not included).&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It also has template- and page-level composition. This enables you to build up sample pages, illustrating how the patterns might work together. From a technical perspective this is very useful for checking things such as a baseline grid, that can’t be properly set on a pattern in isolation without observing it in a higher-level context. It’s also great for stakeholders’ engagement too! It can sometimes be difficult to communicate the value of a modular build approach to people who are used to thinking of the web in terms of pages not patterns. Being able to mock up a page with real patterns in can help with this.&lt;/p&gt;

&lt;h3 id=&quot;principles&quot;&gt;Principles&lt;/h3&gt;
&lt;p&gt;Before starting work, we agreed a set of principles that would guide our approach to decision-making along the way.&lt;/p&gt;

&lt;h4 class=&quot;no_toc&quot; id=&quot;dont-lock-out-the-readers&quot;&gt;Don’t lock out the readers&lt;/h4&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Progressively enhance&lt;/strong&gt;: a reader could be on any platform anywhere in the world. It’s vital that the content (mainly results of scientific research) and core functionality be available to everyone, regardless of platform, so we couldn’t mandate a high technological baseline in order to read the journal. For this reason, and to be a good web citizen generally, we would use a &lt;a href=&quot;https://alistapart.com/article/understandingprogressiveenhancement&quot;&gt;progessive enhancement&lt;/a&gt; approach to ensure that JavaScript is not required to use the site: you get an enhanced experience if it’s available, but content and core functionality does not require it.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Make it responsive&lt;/strong&gt;: it should be a given these days, but it’s worth mentioning anyway that the website should be &lt;a href=&quot;https://www.smashingmagazine.com/2011/01/guidelines-for-responsive-web-design/&quot;&gt;responsive&lt;/a&gt;, so it will display appropriately, whatever the size of the users’ screens.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Make it performant&lt;/strong&gt;: no one likes waiting for a web page to load and, if it takes too long, users will bail. If a user is on a narrow bandwidth or a high-latency connection, then any performance problems are exacerbated. Data costs vary across the world, and we don’t want it to cost more in data charges than necessary to read our content. Performance was considered throughout the build, using ideas of a performance budget, techniques such as responsive images, allowing for the HTTP/2 serving of smaller resources, and not using a library unless we needed it.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Make it accessible&lt;/strong&gt;: it’s vital that our site content is accessible to all to read and use.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h4 class=&quot;no_toc&quot; id=&quot;maintain-the-value-of-the-pattern-library&quot;&gt;Maintain the value of the pattern library&lt;/h4&gt;

&lt;p&gt;One of the aims of a pattern library is to be the canonical source of truth for the design and front end implementation of the design patterns. This is the case at launch, but it’s common for the value of a pattern library to drop dramatically over time if it’s not easy to update, or it’s difficult to do so in a way that maintains the value of the underlying design system.&lt;/p&gt;

&lt;p&gt;After launch, pattern libraries are often susceptible to ‘pattern rot’, when for whatever reason the patterns used on the live website are updated, but the pattern library is not. This usually occurs when there is some kind of copy/paste step necessary in order to apply an update from a pattern library pattern to its version on the live site. This step needs to be short-circuited only once by the update being applied only to the live site, for the pattern library and the live site to diverge. Once this happens, the pattern library is no longer the canonical source of truth, so you can no longer have complete confidence that what you see in the pattern library is what you get on the site. Much of the work that went into building the pattern library becomes lost.&lt;/p&gt;

&lt;p&gt;In summary, for a pattern library to retain its value, it must:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Be built in such a way as to reflect the intent of the design system.&lt;/li&gt;
  &lt;li&gt;Be easy to maintain.&lt;/li&gt;
  &lt;li&gt;Be as easy as possible to integrate into the website it’s defining the patterns for (avoid ‘pattern rot’).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Integration is the hardest problem to solve and has been the holy grail for pattern libraries for years. We managed to crack this, but you’ll have to wait for the companion post to find out how!&lt;/p&gt;

&lt;h4 class=&quot;no_toc&quot; id=&quot;aims&quot;&gt;Aims&lt;/h4&gt;

&lt;p&gt;Before we started writing code, we documented our lower-level aims, based on the principles we’d already decided upon. Our priority of concerns, in decreasing order, were:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Access.&lt;/li&gt;
  &lt;li&gt;Maintainability.&lt;/li&gt;
  &lt;li&gt;Performance.&lt;/li&gt;
  &lt;li&gt;Taking advantage of browser capabilities.&lt;/li&gt;
  &lt;li&gt;Visual appeal.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With the assumption that maintainability won’t negatively impact performance.&lt;/p&gt;

&lt;p&gt;We also documented some of the techniques we’d use:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Progressive enhancement.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;min-width&lt;/code&gt; media queries.&lt;/li&gt;
  &lt;li&gt;Small-screen first responsive images.&lt;/li&gt;
  &lt;li&gt;Only add libraries as needed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;identifying-and-naming-the-patterns&quot;&gt;Identifying and naming the patterns&lt;/h3&gt;
&lt;p&gt;Before we could build any patterns, we needed to identify what things we were building and decide how to talk about them: without a common vocabulary, things could fall apart very quickly. So, embarking on building a brand new look for an online-only journal, we took a large slice of irony pie and started by printing off wireframes of all the patterns.&lt;/p&gt;

&lt;p&gt;Having cut out each pattern, we took up most of the floor of the room we were in, laying them out to take stock of what we had. We grouped similar patterns together, enabling us to distinguish those that were essentially duplicates from those we could treat as variants of the same underlying pattern, and to confirm which were actually distinct patterns.&lt;/p&gt;

&lt;p&gt;Once distinct patterns were identified, we opened up the room to anyone who wanted to help us agree names for each pattern. Fresh minds at this point helped us get better names.&lt;/p&gt;

&lt;p&gt;We thought the whole process would take a couple of hours, but it took most of a day to complete. The benefits were well worth the time: it was a great way to expose many hidden assumptions, identify gaps in thinking, and discover inconsistencies that had crept in during the design process. If we hadn’t done the exercise, all those problems would still exist, but they’d have only manifested later when they’d be more expensive in time and effort to fix.&lt;/p&gt;

&lt;h2 id=&quot;deciding-on-a-process&quot;&gt;Deciding on a process&lt;/h2&gt;
&lt;p&gt;With two front end developers liaising closely with the product team (the designer and the product owner), and facilitated by our tireless scrum master, we decided on 2 week scrum sprints, managing the scrum board in Trello.&lt;/p&gt;

&lt;h3 id=&quot;tickets&quot;&gt;Tickets&lt;/h3&gt;

&lt;p&gt;The fact that we were using progressive enhancement affected the tickets we created: each pattern had a &lt;strong&gt;first pass&lt;/strong&gt; ticket for building its markup and CSS. We used a checklist to manage the work for each ticket:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Semantic html is built.&lt;/li&gt;
  &lt;li&gt;CSS is applied correctly&lt;/li&gt;
  &lt;li&gt;Core content and functionality is available without JavaScript or CSS.&lt;/li&gt;
  &lt;li&gt;Accessibility testing performed.&lt;/li&gt;
  &lt;li&gt;Browser testing performed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If a pattern had some behaviour, then a &lt;strong&gt;second pass&lt;/strong&gt; ticket was created for building its JavaScript. Each second pass ticket had the checklist:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;JavaScript tests written.&lt;/li&gt;
  &lt;li&gt;JavaScript behaviour written.&lt;/li&gt;
  &lt;li&gt;JavaScript tests pass.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For patterns that had variants, the one ticket described building all the variants. They would all have to be considered at the same time in order to build them in a way that works for all of the variants anyway, so it didn’t make sense to split them up.&lt;/p&gt;

&lt;p&gt;Individual tickets had additional, pattern-specific checklist items as necessary.&lt;/p&gt;

&lt;h3 id=&quot;board&quot;&gt;Board&lt;/h3&gt;

&lt;p&gt;The &lt;a href=&quot;https://trello.com/&quot;&gt;Trello&lt;/a&gt; board was initially created with the columns:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Backlog (all tickets start here).&lt;/li&gt;
  &lt;li&gt;Aprint items (committed to in the current sprint).&lt;/li&gt;
  &lt;li&gt;In progress (in active development).&lt;/li&gt;
  &lt;li&gt;In testing (in browser/accessibility testing).&lt;/li&gt;
  &lt;li&gt;In review (being reviewed).&lt;/li&gt;
  &lt;li&gt;Done (finished).&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 class=&quot;no_toc&quot; id=&quot;refinement&quot;&gt;Refinement&lt;/h4&gt;

&lt;p&gt;We discovered in the first retrospective that the product team were not feeling sufficiently involved in the review process for a pattern, resulting in patterns sometimes being classed as done when they weren’t. This was quickly addressed in two ways:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;the addition of two more columns to separate out the product review from the technical review. The board columns were then:&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;Backlog (to be done).&lt;/li&gt;
      &lt;li&gt;Sprint items (committed to in the current sprint).&lt;/li&gt;
      &lt;li&gt;In progress (in active development).&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;For feeback (ready for product review)&lt;/strong&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Feedback provided (reviewed by product)&lt;/strong&gt;.&lt;/li&gt;
      &lt;li&gt;In testing (in browser/accessibility testing).&lt;/li&gt;
      &lt;li&gt;In review (in &lt;strong&gt;technical&lt;/strong&gt; review).&lt;/li&gt;
      &lt;li&gt;Done (finished).&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The addition of an approval checklist, with each product team member having a dedicated box to check to indicate sign off.&lt;/p&gt;

    &lt;p&gt;With the revised board, once the pattern is built and ready for product approval it’s moved from ‘in progress’ to ‘for feedback’. The product team members then either specify any changes to be made, or check their name off the checklist if happy with the pattern as it is. They then move it to ‘feedback provided’. Tickets may go round the ‘for feedback’ -&amp;gt; ‘feedback provided’ -&amp;gt; ‘for feedback’… loop a number of times until the pattern’s right. Once a ticket arrives in ‘feedback provided’ with all product team members’ approval boxes checked, the pattern’s ready for testing.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;code-management&quot;&gt;Code management&lt;/h3&gt;

&lt;p&gt;Pull requests on GitHub from feature branches into the master branch.&lt;/p&gt;

&lt;h2 id=&quot;build&quot;&gt;Build&lt;/h2&gt;

&lt;p&gt;Currently the pattern library defines just under 100 patterns. Each pattern comprises:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Exactly one &lt;code class=&quot;highlighter-rouge&quot;&gt;.scss&lt;/code&gt; file.&lt;/li&gt;
  &lt;li&gt;Exactly one &lt;code class=&quot;highlighter-rouge&quot;&gt;.mustache&lt;/code&gt; file.&lt;/li&gt;
  &lt;li&gt;One or more &lt;code class=&quot;highlighter-rouge&quot;&gt;.json&lt;/code&gt; files, one per pattern variant.&lt;/li&gt;
  &lt;li&gt;Zero or one &lt;code class=&quot;highlighter-rouge&quot;&gt;.js&lt;/code&gt; files, built in the second pass.&lt;/li&gt;
  &lt;li&gt;Exactly one &lt;code class=&quot;highlighter-rouge&quot;&gt;.yaml&lt;/code&gt; file to define the data structure. This is helpful when integrating the patterns into the site and will be expanded on in the forthcoming companion post.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each pattern’s accessibility was tested using Khan Academy’s &lt;a href=&quot;https://khan.github.io/tota11y/&quot;&gt;tota11y&lt;/a&gt; for accessibility testing in the browser.&lt;/p&gt;

&lt;p&gt;We used &lt;a href=&quot;https://www.browserstack.com/&quot;&gt;Browserstack&lt;/a&gt; for browser/device testing.&lt;/p&gt;

&lt;h3 id=&quot;basic-build-pipeline&quot;&gt;Basic build pipeline&lt;/h3&gt;

&lt;p&gt;Although PatternLab can compile SCSS, we elected not to do this as we wanted to control the SCSS compilation with the build pipeline. We started off with a minimal build pipeline, originally in &lt;a href=&quot;https://gruntjs.com/&quot;&gt;Grunt&lt;/a&gt; (we switched to &lt;a href=&quot;https://gulpjs.com/&quot;&gt;Gulp&lt;/a&gt; when we introduced JavaScript, see below), knowing that we could add to it when we needed to. Initially it was only for linting and compiling SCSS, and moving asset files where they needed to be for the PatternLab server to display them correctly.&lt;/p&gt;

&lt;h3 id=&quot;scss&quot;&gt;SCSS&lt;/h3&gt;

&lt;h4 class=&quot;no_toc&quot; id=&quot;style&quot;&gt;Style&lt;/h4&gt;

&lt;p&gt;We agreed a few simple rules with the aim of keeping the SCSS maintainable in the longer term:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;One SCSS file per pattern.&lt;/li&gt;
  &lt;li&gt;Use &lt;a href=&quot;https://csswizardry.com/2013/01/mindbemding-getting-your-head-round-bem-syntax/&quot;&gt;Harry Robert’s flavour of BEM&lt;/a&gt; (Block, Element, Modifier) for CSS class naming. This works well with a pattern-based approach, as the root of each pattern can define a BEM block. Coupled with the decision to have one SCSS file per pattern, this namespacing kept the separation of the styles for individial patterns nice and clean.&lt;/li&gt;
  &lt;li&gt;Keep selector specificity as low as possible, and with a maximum selector nesting of 3 (not including pseudo elements). As selectors need only to start from the root of a pattern (or deeper), this seemed a pragmatic maximum. We agreed that we’d increase it if we really, &lt;em&gt;really&lt;/em&gt; needed to, but up to now we haven’t had to.&lt;/li&gt;
  &lt;li&gt;Don’t use &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;amp;&lt;/code&gt; as partial completion for a class name, as it makes searching/refactoring across a code base more error-prone.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.sitepoint.com/avoid-sass-extend/&quot;&gt;Avoid &lt;code class=&quot;highlighter-rouge&quot;&gt;@extends&lt;/code&gt;&lt;/a&gt;; use mixins instead for greater flexibility.&lt;/li&gt;
  &lt;li&gt;Only mixins that are completely pattern-specific may live in a pattern’s SCSS file, other mixins must live in higher-level files (see Architecture).&lt;/li&gt;
  &lt;li&gt;List property names alphabetically.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We implemented style linting with &lt;a href=&quot;https://stylelint.io/&quot;&gt;stylelint&lt;/a&gt;.&lt;/p&gt;

&lt;h4 class=&quot;no_toc&quot; id=&quot;architecture&quot;&gt;Architecture&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;Meaningful values for the design system: colours, font sizes, quantities for spacing and element sizing, media query breakpoints and transition parameters etc are defined in the &lt;code class=&quot;highlighter-rouge&quot;&gt;variables&lt;/code&gt; partial.&lt;/li&gt;
  &lt;li&gt;For a sensible reset starting point we included &lt;a href=&quot;http://nicolasgallagher.com/about-normalize-css/&quot;&gt;Nicholas Gallagher’s &lt;code class=&quot;highlighter-rouge&quot;&gt;normalise&lt;/code&gt; CSS stylesheet&lt;/a&gt; as an SCSS partial.&lt;/li&gt;
  &lt;li&gt;Our own base styles, and any necessary overrides to &lt;code class=&quot;highlighter-rouge&quot;&gt;normalise&lt;/code&gt; are defined in the &lt;code class=&quot;highlighter-rouge&quot;&gt;normalise-overrides&lt;/code&gt; partial.&lt;/li&gt;
  &lt;li&gt;The typography component of the design system is defined in the &lt;code class=&quot;highlighter-rouge&quot;&gt;typographic-hierarchy&lt;/code&gt; partial: this contains numerous mixins responsible for enforcing a consistent typographic style across the site.&lt;/li&gt;
  &lt;li&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;grid&lt;/code&gt; partial contains all SCSS and mixins required for both the horizontal and baseline grid systems.&lt;/li&gt;
  &lt;li&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;mixins&lt;/code&gt; partial contains all other mixins.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are imported along with the pattern-specific SCSS files to create the main build CSS file like this:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;build.scss
├── base.scss
│   ├── _definitions
│   │   ├── _variables
│   │   ├── _mixins
│   │   └── _typographic-hierarchy
│   ├── reset
│   │   ├── _normalize
│   │   ├── _normalize-overrides
│   └── _grid
├── pattern-1.scss
├── pattern-2.scss
├── pattern-3.scss
├── ...
└── pattern-n.scss
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Each individual &lt;code class=&quot;highlighter-rouge&quot;&gt;[pattern].scss&lt;/code&gt; file also imports the &lt;code class=&quot;highlighter-rouge&quot;&gt;definitions&lt;/code&gt; partial so it has access to all the necessary shared knowledge of the design system as distilled into the variables and various mixins.&lt;/p&gt;

&lt;p&gt;With an eye on delivery over HTTP/2, we ensured that we could produce individual pattern-level CSS files as well as one main stylesheet for traditional HTTP/1.1 delivery.&lt;/p&gt;

&lt;h3 id=&quot;organising-the-typography&quot;&gt;Organising the typography&lt;/h3&gt;
&lt;p&gt;The designer documented the typographical part of the design system as a hierarchy of definitions. The lowest level is used to set relevent variables in &lt;code class=&quot;highlighter-rouge&quot;&gt;variables&lt;/code&gt;, and set the base styles in &lt;code class=&quot;highlighter-rouge&quot;&gt;normalise-overrides&lt;/code&gt;.&lt;/p&gt;

&lt;table&gt;
&lt;caption&gt;Example of base styles for design system typography&lt;/caption&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Style name&lt;/th&gt;
&lt;th&gt;Default narrow screen&lt;/th&gt;
&lt;th&gt;Media query&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;

&lt;tr&gt;          
&lt;td&gt;Body&lt;/td&gt;
&lt;td&gt;PT Serif 16px/1.5 space after 24px&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;          
&lt;td&gt;H1&lt;/td&gt;
&lt;td&gt;Avenir Next Demi Bold 24px/1.3&lt;/td&gt;
&lt;td&gt;Font-size 36px&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;          
&lt;td&gt;H2&lt;/td&gt;
&lt;td&gt;Avenir Next Demi Bold 21px/1.3 space after 5px&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;

&lt;tr aria-hidden=&quot;true&quot;&gt;
&lt;td colspan=&quot;3&quot;&gt;...&lt;/td&gt;
&lt;/tr&gt;

&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;The media query column specifies what (if any) change occurs when the viewport is wider than the relevant site breakpoint. Note that the breakpoints themselves are not specified here, to keep things loosely coupled.&lt;/p&gt;

&lt;p&gt;These base styles are then used as part of the specification for the next level up:&lt;/p&gt;

&lt;table&gt;
&lt;caption&gt;Example of title styles, extending base styles&lt;/caption&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Style name&lt;/th&gt;
&lt;th&gt;Default narrow screen&lt;/th&gt;
&lt;th&gt;Media query&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;

&lt;tr&gt;          
&lt;td&gt;Title-lg&lt;/td&gt;
&lt;td&gt;PT Serif 16px/1.5 space after 24px&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;          
&lt;td&gt;Title-md&lt;/td&gt;
&lt;td&gt;h1 font-size 42px&lt;/td&gt;
&lt;td&gt;Font-size 54px&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;          
&lt;td&gt;Title-sm&lt;/td&gt;
&lt;td&gt;h1 font-size 30px&lt;/td&gt;
&lt;td&gt;Font-size 44px&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;          
&lt;td&gt;Title-xs&lt;/td&gt;
&lt;td&gt;h1&lt;/td&gt;
&lt;td&gt;Font-size 36px&lt;/td&gt;
&lt;/tr&gt;

&lt;tr aria-hidden=&quot;true&quot;&gt;
&lt;td colspan=&quot;3&quot;&gt;...&lt;/td&gt;
&lt;/tr&gt;

&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;These all specify different title sizes (which one gets applied depends on how long the title is).&lt;/p&gt;

&lt;p&gt;Typographical styles are defined for all aspects of the design, like this tiny fraction of the set:&lt;/p&gt;

&lt;table&gt;
&lt;caption&gt;Example of more typographical styles&lt;/caption&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Style name&lt;/th&gt;
&lt;th&gt;Default narrow screen&lt;/th&gt;
&lt;th&gt;Media query&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;

&lt;tr&gt;          
&lt;td&gt;CONTENT LABEL [grey]&lt;/td&gt;
&lt;td&gt;Avenir Next Demi Bold, 11px/1&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;          
&lt;td&gt;SUBJECT LABEL [blue]&lt;/td&gt;
&lt;td&gt;Avenir Next Demi Bold, 11px/1&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;          
&lt;td&gt;Article title (main list)&lt;/td&gt;
&lt;td&gt;h2&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;          
&lt;td&gt;Article title (side list)&lt;/td&gt;
&lt;td&gt;PT Serif Bold 16px&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;

&lt;tr aria-hidden=&quot;true&quot;&gt;
&lt;td colspan=&quot;3&quot;&gt;...&lt;/td&gt;
&lt;/tr&gt;


&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;All these definitions are captured in mixins within &lt;code class=&quot;highlighter-rouge&quot;&gt;typographical-hierarchy&lt;/code&gt;. For example, for the two labels, we abstract out the common aspects:&lt;/p&gt;
&lt;div class=&quot;language-scss highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;c1&quot;&gt;// All typographical style mixin names include 'typeg' for clarity
&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// when viewed out of context. 
&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;@mixin&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;_label-typeg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;nl&quot;&gt;font-family&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$font-secondary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;nl&quot;&gt;font-weight&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;normal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;@include&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;font-size-and-vertical-height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;11&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
   &lt;span class=&quot;nl&quot;&gt;letter-spacing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;.5px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;nl&quot;&gt;text-transform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;uppercase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;and then create a mixin for each label type, based on it:&lt;/p&gt;

&lt;div class=&quot;language-scss highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;k&quot;&gt;@mixin&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;label-content-typeg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;@include&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;_label-typeg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
   &lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$color-text-secondary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// grey
&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

 &lt;span class=&quot;k&quot;&gt;@mixin&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;label-subject-typeg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;@include&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;_label-typeg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
   &lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$color-primary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// blue
&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In the design system specification, all the patterns have their typography defined in terms of these typographical style names. Often a particular style name is used for more than one pattern. With this approach, we can easily apply the correct typographical style to the pattern’s CSS via the mixins and, at the same time, keep the design system highly maintainable. If a particular named style is updated, then a simple update to one &lt;code class=&quot;highlighter-rouge&quot;&gt;typeg&lt;/code&gt; mixin will permeate to all parts of the system that use it.&lt;/p&gt;

&lt;p&gt;(N.B. These examples are taken from an early draft of the spec and the final values used on the site may have changed, although the system defining them hasn’t, indicating that it’s working well!)&lt;/p&gt;

&lt;h3 id=&quot;markup&quot;&gt;Markup&lt;/h3&gt;
&lt;p&gt;Compilation of the mustache templates with their json data files is handled by PatternLab, producing a user-friendly, to-some-extent-configurable, &lt;a href=&quot;https://ui-patterns.elifesciences.org/&quot;&gt;web view of the patterns&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A basic pattern with no variants has exactly one mustache template and one corresponding &lt;code class=&quot;highlighter-rouge&quot;&gt;json&lt;/code&gt; data file.&lt;/p&gt;

&lt;h4 class=&quot;no_toc&quot; id=&quot;pattern-variants&quot;&gt;Pattern variants&lt;/h4&gt;

&lt;p&gt;For a more complex pattern that has variants, an example of each variant can be produced by supplying a separate &lt;code class=&quot;highlighter-rouge&quot;&gt;json&lt;/code&gt; file for each. For example the teaser pattern has  13 variants (an extreme case, most variant patterns have fewer than a handful). It has only one &lt;code class=&quot;highlighter-rouge&quot;&gt;mustache&lt;/code&gt; file, but 13 associated &lt;code class=&quot;highlighter-rouge&quot;&gt;json&lt;/code&gt; files:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;.
├── teaser.mustache
├── teaser~05-main.json
├── teaser~10-main-small-image.json
├── teaser~15-main-big-image.json
├── teaser~20-secondary.json
├── teaser~25-secondary-small-image.json
├── teaser~30-secondary-big-image.json
├── teaser~35-related-item.json
├── teaser~40-basic.json
├── teaser~45-main-event.json
├── teaser~50-secondary-event.json
├── teaser~55-grid-style--labs.json
├── teaser~60-grid-style--podcast.json
└── teaser~65-main--with-list.json
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;PatternLab uses the &lt;code class=&quot;highlighter-rouge&quot;&gt;~&lt;/code&gt; in a filename to identify a variant. The numerals in the filenames control the ordering of the &lt;a href=&quot;https://ui-patterns.elifesciences.org/?p=viewall-molecules-teasers&quot;&gt;presentation of the variants&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Sometimes when coming to build a pattern with variants, we discovered that one or more variants required a significant change to the markup of the main pattern, which suggested a new pattern rather than just a variant. In this case we’d create the ticket(s) for it and put them into the backlog, moving the appropriate spec from the old to the new ticket.&lt;/p&gt;

&lt;h3 id=&quot;images&quot;&gt;Images&lt;/h3&gt;
&lt;p&gt;The scholarly content contains a lot of figures, mainly in the form of images. We use &lt;a href=&quot;https://responsiveimages.org/&quot;&gt;responsive images techniques&lt;/a&gt; (&lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;picture&amp;gt;&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;srcset&lt;/code&gt; and sometimes &lt;code class=&quot;highlighter-rouge&quot;&gt;sizes&lt;/code&gt;) to stop the browser downloading more image data than it needs. For example, the compiled HTML from the &lt;code class=&quot;highlighter-rouge&quot;&gt;captioned-asset&lt;/code&gt; pattern’s mustache template looks like this:&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;figure&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;captioned-asset&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
 
   &lt;span class=&quot;nt&quot;&gt;&amp;lt;picture&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;captioned-asset__picture&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
     &lt;span class=&quot;nt&quot;&gt;&amp;lt;source&lt;/span&gt; 
       &lt;span class=&quot;na&quot;&gt;srcset=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;
         /path-to-1076-px-wide-image 1076w, 
         /path-to-538-px-wide-image 538w&quot;&lt;/span&gt; 
       &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;image/jpeg&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
     &lt;span class=&quot;nt&quot;&gt;&amp;lt;img&lt;/span&gt; 
       &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/path-to-538-px-wide-image&quot;&lt;/span&gt; 
       &lt;span class=&quot;na&quot;&gt;alt=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;
       &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;captioned-asset__image&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
   &lt;span class=&quot;nt&quot;&gt;&amp;lt;/picture&amp;gt;&lt;/span&gt;         

   &lt;span class=&quot;nt&quot;&gt;&amp;lt;figcaption&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;captioned-asset__caption&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;          
     &lt;span class=&quot;nt&quot;&gt;&amp;lt;h6&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;caption-text__heading&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Title of the figure caption&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h6&amp;gt;&lt;/span&gt;
     &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;caption-text__body&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;The figure caption&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
     &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;doi doi--asset&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;The DOI link&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
   &lt;span class=&quot;nt&quot;&gt;&amp;lt;/figcaption&amp;gt;&lt;/span&gt;

 &lt;span class=&quot;nt&quot;&gt;&amp;lt;/figure&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Note the empty &lt;code class=&quot;highlighter-rouge&quot;&gt;alt&lt;/code&gt; attribute: as the image is within a &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;figure&amp;gt;&lt;/code&gt;, the &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;figcaption&amp;gt;&lt;/code&gt; provides the description.&lt;/p&gt;

&lt;p&gt;To handle the large amount of image variants that can be required when implementing responsive images, we used the &lt;a href=&quot;http://iiif.io/&quot;&gt;International Image Interoperability Framework&lt;/a&gt; (IIIF) &lt;a href=&quot;https://elifesciences.org/labs/d6044799/dynamically-serving-scientific-images-using-iiif&quot;&gt;to serve most of our images&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;extended-build-pipeline&quot;&gt;Extended build pipeline&lt;/h3&gt;
&lt;p&gt;When we came to build the patterns’ behaviours, we needed to add JavaScript linting, transpiling and test running to the build pipeline. It quickly became apparent that Gulp was much more flexible than Grunt for this, so we switched from a wild boar to a huge caffeinated beverage (and the caffeine would come in handy).&lt;/p&gt;

&lt;p&gt;We author in ES6, and use Babel to transpile down to ES2015, because when we started this project at the beginning of 2016, ES2015 was the generally recommended target. Nearly 2 years later, the JavaScript/Browser landscape has changed considerably, and we’ll be reviewing this fairly soon.&lt;/p&gt;

&lt;p&gt;Linting is performed with a mixture of &lt;a href=&quot;http://jshint.com/&quot;&gt;jshint&lt;/a&gt; and &lt;a href=&quot;http://jscs.info/&quot;&gt;jscs&lt;/a&gt;, although there is a pending upgrade to &lt;a href=&quot;https://eslint.org/&quot;&gt;eslint&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;pattern-behaviour-with-javascript&quot;&gt;Pattern behaviour with JavaScript&lt;/h3&gt;
&lt;p&gt;A pattern’s JavaScript behaviour is defined in a discrete component with the same name as the pattern. This JavaScript component is referenced from the root element of the pattern’s mustache template by the attribute &lt;code class=&quot;highlighter-rouge&quot;&gt;data-behaviour=&quot;ComponentName&quot;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example, the content-header pattern has its associated behaviour defined in the &lt;code class=&quot;highlighter-rouge&quot;&gt;ContentHeader&lt;/code&gt; class, which is found in the &lt;code class=&quot;highlighter-rouge&quot;&gt;ContentHeader.js&lt;/code&gt; file. The &lt;code class=&quot;highlighter-rouge&quot;&gt;content-header.mustache&lt;/code&gt; template starts with:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;div... data-behaviour=&quot;ContentHeader&quot;&amp;gt;...&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This causes this HTML element to be passed as an argument to the class constructor in &lt;code class=&quot;highlighter-rouge&quot;&gt;ContentHeader.js&lt;/code&gt; when the page’s JavaScript loads and runs:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;c1&quot;&gt;// 1. Load the components&lt;/span&gt;
 &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Components&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{};&lt;/span&gt;
 &lt;span class=&quot;nx&quot;&gt;Components&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ContentHeader&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'./components/ContentHeader'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
 &lt;span class=&quot;c1&quot;&gt;// ... load more components ...&lt;/span&gt;

 &lt;span class=&quot;c1&quot;&gt;// 4. This bit does the actual initialising&lt;/span&gt;
 &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;initialiseComponent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$component&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;handler&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$component&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getAttribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'data-behaviour'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Components&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Components&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'function'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
     &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Components&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$component&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      
   &lt;span class=&quot;nx&quot;&gt;$component&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dataset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;behaviourInitialised&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    
 &lt;span class=&quot;c1&quot;&gt;// 2. Find all patterns in the document that have declared  a js component&lt;/span&gt;
 &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;components&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;querySelectorAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'[data-behaviour]'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    
 &lt;span class=&quot;c1&quot;&gt;// 3. Initialise each component with the HTMLElement that declared it&lt;/span&gt;
 &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;components&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;[].&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;components&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;el&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;initialiseComponent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;el&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;  
 &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This applies the pattern’s JavaScript behaviour to each instance of the pattern on the page.&lt;/p&gt;

&lt;p&gt;Notice we’re additionally passing in the &lt;code class=&quot;highlighter-rouge&quot;&gt;window&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;document&lt;/code&gt; objects to the component’s constructor. This dependency injection enables us to mock these objects, enabling us to write better tests.&lt;/p&gt;

&lt;h4 class=&quot;no_toc&quot; id=&quot;future-improvements&quot;&gt;Future improvements&lt;/h4&gt;

&lt;p&gt;It’d be great to improve the loader so that only the components on a particular page are loaded, and then initialisation can occur after these loads have completed.&lt;/p&gt;

&lt;p&gt;Because we have a 1:1 relationship between JavaScript component and pattern, we should be able to support HTTP/2 delivery of individual JavaScript assets, only providing what is required to the client (once we’ve upgraded our CDN).&lt;/p&gt;

&lt;h3 id=&quot;javascript-testing&quot;&gt;JavaScript testing&lt;/h3&gt;

&lt;p&gt;We test in the browser using the tripod of the &lt;a href=&quot;https://mochajs.org/&quot;&gt;mocha&lt;/a&gt; test framework, the &lt;a href=&quot;http://chaijs.com/&quot;&gt;chai&lt;/a&gt; assertion library, and with &lt;a href=&quot;http://sinonjs.org/&quot;&gt;sinon&lt;/a&gt; for providing spies, mocks and stubs. At the moment we’re using phantomjs as the test environment, but now that’s not currently under active maintenance we’re looking to switch to using puppeteer with headless Chrome.&lt;/p&gt;

&lt;p&gt;For each pattern under test there are two files: the spec file and the fixture file. The spec file contains the tests. The fixture file contains the HTML of the pattern whose component is under test. This is obtained by finding the pattern’s compiled HTML generated by PatternLab, and manually copying across the relevant code.&lt;/p&gt;

&lt;p&gt;By way of example, this is the guts of the fixture file for the &lt;code class=&quot;highlighter-rouge&quot;&gt;ToggleableCaption&lt;/code&gt; component:&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;c&quot;&gt;&amp;lt;!-- Results of test run end up here --&amp;gt;&lt;/span&gt;
 &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;mocha&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
 
 &lt;span class=&quot;c&quot;&gt;&amp;lt;!-- This is the test fixture --&amp;gt;&lt;/span&gt; 
 &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;data-behaviour=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ToggleableCaption&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;data-selector=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;.caption-text__body&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
 
   &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;caption-text__body&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
 
     &lt;span class=&quot;nt&quot;&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Lorem ipsum dolor sit amet, consectetur adipiscing elit. In interdum, metus quis sodales pharetra, odio justo
       blandit mi, at porta augue felis sit amet metus. Aliquam porta, justo dapibus vulputate aliquet, arcu quam tempor
       metus, et aliquam nisi nunc in est. Cras vitae leo pretium, tincidunt nisi ac, varius neque. Donec nec posuere
       sem. Integer felis risus, sagittis et pulvinar pretium, rutrum sit amet odio. Proin erat purus, sodales a gravida
       vitae, malesuada non sem. Integer semper enim ante. Donec odio ipsum, ultrices vel quam at, condimentum eleifend
       augue. Pellentesque id ipsum nec dui dictum commodo. Donec quis sagittis ex, sit amet tempus nisi. Nulla eu tortor
       vitae felis porta faucibus in eu leo. Donec ultrices vehicula enim, quis maximus nulla rhoncus sed. Vestibulum
       elementum ligula quis mi aliquet, tincidunt finibus mi hendrerit.&lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
 
   &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
 
 &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
 
 &lt;span class=&quot;c&quot;&gt;&amp;lt;!-- Load the test frameworks --&amp;gt;&lt;/span&gt;
 &lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;../node_modules/mocha/mocha.js&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
 &lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;../node_modules/chai/chai.js&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
 &lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;../node_modules/sinon/pkg/sinon.js&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
 
 &lt;span class=&quot;c&quot;&gt;&amp;lt;!-- Initialise the test suite --&amp;gt;&lt;/span&gt;
 &lt;span class=&quot;nt&quot;&gt;&amp;lt;script&amp;gt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mocha&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'bdd'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
 
 &lt;span class=&quot;c&quot;&gt;&amp;lt;!-- Load the spec file --&amp;gt;&lt;/span&gt;
 &lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;build/toggleablecaption.spec.js&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
 
 &lt;span class=&quot;c&quot;&gt;&amp;lt;!-- Run the tests --&amp;gt;&lt;/span&gt;
 &lt;span class=&quot;nt&quot;&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
   &lt;span class=&quot;nx&quot;&gt;mocha&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
 &lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We’ve found that keeping the test fixtures up to date can be difficult, because it takes a developer to remember to re-copy and paste the HTML from the compiled mustache pattern template every time a pattern’s source or source-generating JavaScript is updated.&lt;/p&gt;

&lt;p&gt;The tests are run under Gulp using &lt;code class=&quot;highlighter-rouge&quot;&gt;gulp-mocha-phantomjs&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;where-is-it-tho&quot;&gt;Where &lt;em&gt;is it&lt;/em&gt; tho’?&lt;/h2&gt;

&lt;p&gt;The website using the patterns is &lt;a href=&quot;https://elifesciences.org/&quot;&gt;https://elifesciences.org/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;All the code for the pattern library is available on GitHub under the MIT licence at &lt;a href=&quot;https://github.com/elifesciences/pattern-library&quot;&gt;https://github.com/elifesciences/pattern-library&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The PatternLab pattern library generated by this code is at &lt;a href=&quot;https://ui-patterns.elifesciences.org/&quot;&gt;https://ui-patterns.elifesciences.org/&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;lessons-learned&quot;&gt;Lessons learned&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Take the time to agree your principles and build aims up front. Set the expectations that derive from these in the wider team, so no one’s surprised when you start challenging demands for moarLibrareez, etc.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;When following Atomic Design principles, don’t worry too much about strict molecule/organism hierarchy: get it as good as you can, but a slighly fuzzy, useable system is better than a system that’s strictly correct but horrible to use.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Implementing a design system requires excellent communication between designers and front end devs. A designer who understands front end code, and developers with a design eye, both really help with this: the more shared context, the better the mutual understanding.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Regularly review your process: if we hadn’t had the retrospective that uncovered the frustrations of the product team over sign off, work quality could have been reduced and relationships strained.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Don’t be afraid to iterate on the patterns, and set the expectation early that this is a good thing. More complex patterns, and/or patterns that have multiple variants may need a few shots at them to make them work. Remember that if you’re implementing a design system, the patterns don’t only have to work individually, but they have to be easily maintainable along with the design system. It’s worth spending more time to iterate to get it right at this stage, because fundamental changes later are bound to be more expensive in time, effort and complexity.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Concentrating the design system typography in one place made thinking about it, talking about it, and subsequently, maintaining it, a lot easier than it might otherwise have been.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;TDD FTW! The few times we didn’t use test-driven development for the JavaScript, it was always painful to fill in the gaps afterwards.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Grunt is good to get up and running quickly for simple build pipelines, but if you’re trying to do more complicated things, it’s probably easier to use Gulp: Gulp build files are written in JavaScript, which is more versatile and less confusing than trying to wrangle a Grunt config JavaScript object for a complex build pipeline.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;in-conclusion&quot;&gt;In conclusion&lt;/h2&gt;

&lt;p&gt;This is one of the most rewarding projects I’ve worked on: a truly honourable combination of open source code enabling open access science publishing. There’s loads more I could say, but this post is already long enough. Be sure to check back soon for the companion post about how we solved pattern rot through enabling use of the patterns we built in PatternLab directly in the website.&lt;/p&gt;
</description>
        <pubDate>Fri, 17 Nov 2017 10:00:00 +0000</pubDate>
        <link>http://decodeuri.net/2017/11/17/building-a-pattern-library-for-scholarly-publishing/</link>
        <guid isPermaLink="true">http://decodeuri.net/2017/11/17/building-a-pattern-library-for-scholarly-publishing/</guid>
        
        
      </item>
    
      <item>
        <title>Detecting keystrokes in the browser</title>
        <description>&lt;h1 id=&quot;keyboardevent-key-reporting&quot;&gt;KeyboardEvent key reporting&lt;/h1&gt;

&lt;p&gt;All verification performed using this test form:&lt;/p&gt;

&lt;iframe src=&quot;/supporting/keys.html&quot; width=&quot;100%&quot; height=&quot;170&quot; style=&quot;outline: 1px solid rgba(42, 122, 226, 0.25); border-width: 0;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;and referring to this &lt;a href=&quot;http://www.ascii-code.com/&quot;&gt;ACSII reference&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;(The &lt;a href=&quot;/supporting/keys.html&quot;&gt;test form is also available separately&lt;/a&gt;.)&lt;/p&gt;

&lt;h2 id=&quot;desktop-and-ios&quot;&gt;Desktop and iOS&lt;/h2&gt;

&lt;p&gt;The modern desktop environment on Mac and PC (Linux not tested), along with iOS seems to behave fairly consistently.&lt;/p&gt;

&lt;p&gt;KeyboardEvents from printable characters and the return key (at least), supply one or both of keyCode and charCode (depending on the browser, see below), for each of keyup, keydown and keypress events.&lt;/p&gt;

&lt;p&gt;Lower case alphabetic characters have their lowercase ASCII value reported for a keypress event, but keyup and keydown events report the ASCII value of the corresponding uppercase character.&lt;/p&gt;

&lt;p&gt;Typing uppercase characters does not exhibit surprising behaviour, but you need to remember to take into account the modifer keys (shift or capslock).&lt;/p&gt;

&lt;p&gt;When an uppercase character is typed by holding down the shift key:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;when the shift key is initially depressed, the keydown event reports that as the value for ‘Data line escape’ (16)&lt;/li&gt;
  &lt;li&gt;all three events register the ASCII value for the upper case character when that is keyed.&lt;/li&gt;
  &lt;li&gt;When the shift key is released, ‘Data line escape’ (16) is reported for the keyup event.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When an uppercase character is typed using capslock:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;when capslock is turned on, the keydown event reports that as the value for ‘Device control 4’ (20)&lt;/li&gt;
  &lt;li&gt;all three events register the ASCII value for the upper case character when that is keyed. This continues as long as capslock is on&lt;/li&gt;
  &lt;li&gt;when capslock is turned off, ‘Device control 4’ (20) is reported for the keyup event.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When shift/caps lock key is keyed on a phone’s soft keyboard, it generates neither a code 16 nor a code 20 for the shift/caps lock key.&lt;/p&gt;

&lt;p&gt;Events from arrow keys provide keyCode values for keyup and keydown, but not for keypress. Not tested on mobile (generally no arrow keys on the soft keyboards, I’ve not tested using external hardware).&lt;/p&gt;

&lt;p&gt;When listening to events on input fields, those from the tab key provide a keyCode value only for keydown, not for the keyup nor keypress events. (This may be because the tab key moves focus away from the element where the keydown event was triggered, meaning that the keyup and keypress events will be never be fired for that specific keying of the tab key, but I’m not sure).&lt;/p&gt;

&lt;h2 id=&quot;android&quot;&gt;Android&lt;/h2&gt;
&lt;p&gt;This is where things get funky. I’ve not carried out an exhaustive test because there are hundreds of types of Android devices. However, playing on my venerable OnePlusOne, and also running the test page on a number of Android setups on Browserstack showed consistent behaviour, as far as it goes. It’s this, and it’s a doozy:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;no matter what character you key in, keypress says nothing, and both keyup and keydown report a keyCode value for ‘Latin small letter a with ring above’ (229).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So every character you type is being reported as å.&lt;/p&gt;

&lt;p&gt;Which is just very slightly wrong.&lt;/p&gt;

&lt;h2 id=&quot;what-to-do&quot;&gt;What to do?&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;when responding to keyup or keydown events, check keyCode for the ASCII value of the uppercase version of the character keyed.&lt;/li&gt;
  &lt;li&gt;when responding to the keypress event, check charCode for the ASCII value of the actual character keyed (some browsers will also report in keyCode, but not all, so charCode’s your best bet).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’m assuming Android’s flakiness is not so critical when detecting tab and arrow keys as they are less likely to be used on a touch screen’s soft keyboard (but there may be people using external keyboards):&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;if you’re looking for the tab key, you need to listen for it on the keydown event to be most sure of getting it. Note that you should not generally try to do things with the tab key as you may break keyboard navigation.&lt;/li&gt;
  &lt;li&gt;if you’re looking for an arrow key, you may choose to listen for it on either the keyup or keydown events.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Other things that seem to apply most places but Android:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;if you’re looking for an alphabetic character but don’t care in what case, listen for it using the keyup or keydown events.&lt;/li&gt;
  &lt;li&gt;if you’re looking for an alphabetic character, and the case in which it was typed matters, listen for it using the keypress event.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You’ll need a fallback strategy for Android. In some situations it might be enough to detect that there’s been a keyup or keydown event and use that to trigger an inspection of something on the page that might have been changed by it (the value of a form field with focus, for example).&lt;/p&gt;

&lt;h2 id=&quot;osx-el-capitan&quot;&gt;OSX El Capitan&lt;/h2&gt;

&lt;h3 id=&quot;chrome&quot;&gt;Chrome&lt;/h3&gt;

&lt;h4 id=&quot;keyup&quot;&gt;keyup&lt;/h4&gt;
&lt;p&gt;says &lt;strong&gt;keyCode&lt;/strong&gt; not charCode&lt;/p&gt;

&lt;p&gt;Reports value of upper case version of the character where appropriate.&lt;/p&gt;

&lt;h4 id=&quot;keydown&quot;&gt;keydown&lt;/h4&gt;
&lt;p&gt;says &lt;strong&gt;keyCode&lt;/strong&gt; not charCode&lt;/p&gt;

&lt;p&gt;Reports value of upper case version of the character where appropriate.&lt;/p&gt;

&lt;h4 id=&quot;keypress&quot;&gt;keypress&lt;/h4&gt;
&lt;p&gt;both &lt;strong&gt;keyCode&lt;/strong&gt; and &lt;strong&gt;charCode&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Reports value of the character that was actually generated (upper- or lowercase).&lt;/p&gt;

&lt;h3 id=&quot;firefox&quot;&gt;Firefox&lt;/h3&gt;

&lt;h4 id=&quot;keyup-1&quot;&gt;keyup&lt;/h4&gt;
&lt;p&gt;says &lt;strong&gt;keyCode&lt;/strong&gt; not charCode&lt;/p&gt;

&lt;p&gt;Reports value of upper case version of the character where appropriate.&lt;/p&gt;

&lt;h4 id=&quot;keydown-1&quot;&gt;keydown&lt;/h4&gt;
&lt;p&gt;says &lt;strong&gt;keyCode&lt;/strong&gt; not charCode&lt;/p&gt;

&lt;p&gt;Reports value of upper case version of the character where appropriate.&lt;/p&gt;

&lt;h4 id=&quot;keypress-1&quot;&gt;keypress&lt;/h4&gt;
&lt;p&gt;not keyCode but &lt;strong&gt;charCode&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Reports value of the character that was actually generated (upper- or lowercase).&lt;/p&gt;

&lt;h3 id=&quot;safari&quot;&gt;Safari&lt;/h3&gt;

&lt;p&gt;Appears to be the same as Chrome.&lt;/p&gt;

&lt;h2 id=&quot;ie&quot;&gt;IE&lt;/h2&gt;

&lt;p&gt;Edge and IE 9 and up exhibit behaviour similiar to Chrome. (IE 8 hasn’t been tested because the test page uses addEventListener that isn’t supported by IE8.)&lt;/p&gt;

</description>
        <pubDate>Thu, 08 Sep 2016 00:30:00 +0000</pubDate>
        <link>http://decodeuri.net/2016/09/08/detecting-key-strokes-in-the-browser/</link>
        <guid isPermaLink="true">http://decodeuri.net/2016/09/08/detecting-key-strokes-in-the-browser/</guid>
        
        
      </item>
    
      <item>
        <title>Smashingconf 2016: day 2</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#design-systems-in-difficult-places&quot; id=&quot;markdown-toc-design-systems-in-difficult-places&quot;&gt;Design systems in difficult places&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#taking-layout-to-the-next-level&quot; id=&quot;markdown-toc-taking-layout-to-the-next-level&quot;&gt;Taking layout to the next level&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#designing-the-future-of-content&quot; id=&quot;markdown-toc-designing-the-future-of-content&quot;&gt;Designing the future of content&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#devtools-an-animated-journey&quot; id=&quot;markdown-toc-devtools-an-animated-journey&quot;&gt;Devtools, an animated journey&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#overthinking-design-and-embracing-minutiae&quot; id=&quot;markdown-toc-overthinking-design-and-embracing-minutiae&quot;&gt;Overthinking design and embracing minutiae&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#living-design-systems&quot; id=&quot;markdown-toc-living-design-systems&quot;&gt;Living Design Systems&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#modern-workflow-and-tooling&quot; id=&quot;markdown-toc-modern-workflow-and-tooling&quot;&gt;Modern workflow and tooling&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#improving-screen-legibibilty&quot; id=&quot;markdown-toc-improving-screen-legibibilty&quot;&gt;Improving screen legibibilty&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(&lt;a href=&quot;/2016/03/18/smashing-conference-2016-day-1/&quot;&gt;Find out what happened on day 1&lt;/a&gt;.)&lt;/p&gt;

&lt;h2 id=&quot;design-systems-in-difficult-places&quot;&gt;Design systems in difficult places&lt;/h2&gt;
&lt;p&gt;(Mark Boulton @markboulton)&lt;/p&gt;

&lt;p&gt;By “Difficult”, he means distributed (across multiple locations), devloved (local decision making) and degrading (customers are exposed to a degredation of the design).&lt;/p&gt;

&lt;p&gt;Grew up in Manchester. Factory records fly stickers all over the city. Got used to seeing them in the environment, absorbed into the zeitgeist. (Was taught by Peter Saville!).&lt;/p&gt;

&lt;p&gt;Benefits of marginal gains: Sky cycling team manager looked at &lt;em&gt;everything&lt;/em&gt; in the lives of his cyclists to attempt many microoptimisations in the hope that accruing enough of them to add up to siginificant improvements in overall performance.&lt;/p&gt;

&lt;p&gt;Corollary is the dangers of marginal degredation: this is where a design system can help.&lt;/p&gt;

&lt;p&gt;Often came across ‘Problem escalation’: design a website turned into change how your team contributes content turned into your whole business process needs an overhaul. As an agency, had no authority to lead on that, all they had were persuation. Not a comfortable position if the sucess of your project depends on being able to persuade.&lt;/p&gt;

&lt;p&gt;Seeing how people work around the awkwardness in a CMS to do their jobs can be great research to feed into the requirements for what replaces it.&lt;/p&gt;

&lt;h3 class=&quot;no_toc&quot; id=&quot;al-jazeera-website-redesign&quot;&gt;Al Jazeera website redesign&lt;/h3&gt;
&lt;p&gt;Editorial values very important to them. Where CNN sanitise’s footage from a war zone, they dont.&lt;/p&gt;

&lt;p&gt;Readers consumed content very differently from how the journalists thought that they did: readers read more than one source; they scan by topic; they evaluated the contents based on the level of trust that they had in the brand, but the journalists were undermining that trust in the way they were presenting their stories.&lt;/p&gt;

&lt;h3 class=&quot;no_toc&quot; id=&quot;cern&quot;&gt;CERN&lt;/h3&gt;

&lt;p&gt;Flat hierarchy, independent-minded constituents. They had no mandate, again were operating on persuation.&lt;/p&gt;

&lt;p&gt;Design system must adapt to serve the communicating of high wonder to the general public, and low wonder for scientists.&lt;/p&gt;

&lt;h3 class=&quot;no_toc&quot; id=&quot;monotype&quot;&gt;Monotype&lt;/h3&gt;

&lt;p&gt;Stu Robson built ‘monotype core’, an npm-built setup that creates a local version of the site with all the correct brand assets, GA code, &amp;amp; other required boilerplate.&lt;/p&gt;

&lt;p&gt;Central policing of brand never works, be where the person is and make it easier for them to do what they want - prevents gradual degredation.&lt;/p&gt;

&lt;p&gt;Everyone wants to be creative. A design system gives people the canvas to do just that, while delineating the constraints, the edges of what they can effect.&lt;/p&gt;

&lt;p&gt;Every system devolves into chaos, every garden needs tending.&lt;/p&gt;

&lt;p&gt;Draw straight lines between design and KPIs:&lt;/p&gt;

&lt;p&gt;research -&amp;gt; design -&amp;gt; outcomes -&amp;gt; KPI&lt;/p&gt;

&lt;p&gt;He’s come to realise that meetings &lt;em&gt;are&lt;/em&gt; the work. “Am I okay with that? I am at the moment, but maybe ask me again in a year.”&lt;/p&gt;

&lt;p&gt;Establish a mandate if you can, otherwise you need to do lots of convincing and need a lot of good will.&lt;/p&gt;

&lt;p&gt;How do you know when you’re successful?&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;there’s a shared vocabulary in use, e.g. “wonder” at CERN.&lt;/li&gt;
  &lt;li&gt;the system becomes self policing, that means people care.&lt;/li&gt;
  &lt;li&gt;design health. This can be a leading indicator, the canary in the gold mine.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;taking-layout-to-the-next-level&quot;&gt;Taking layout to the next level&lt;/h2&gt;
&lt;p&gt;(Christopher Wright @cwrightdesign)&lt;/p&gt;

&lt;p&gt;Works at Campaign Monitor in Sydney [knows John Allsopp]
He’s done Flexbox Adventures &amp;amp; Using flexbox today (look these up). Advocates learing in the open, writing about things as you learn, not after you’ve learnt, so you can document the small things that make it work, but that you mauy forget afterwards: better to help others learn.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;EXPERIMENT!&lt;/em&gt; Fail early, learn faster.&lt;/p&gt;

&lt;h3 class=&quot;no_toc&quot; id=&quot;simplicity&quot;&gt;Simplicity&lt;/h3&gt;

&lt;p&gt;Rise of complexity, try to manage it with things like SASS or Bootstrap.&lt;/p&gt;

&lt;p&gt;Pattern approach good, helps avoid progressive degredation (see Marks Bolton’s talk), but things aren’t that simple&lt;/p&gt;

&lt;p&gt;CSS gave us abstracted layouts, where a component is controlled by its ancestors, i.e. the grid.&lt;/p&gt;

&lt;p&gt;Content-based breakpoints are good, but you can end up with very, very many media queries. Most frameworks addressed this by focusing on devices, e.g. Bootstrap or Foundation. Booooo. The problem is forcing the component to respond to screen size.&lt;/p&gt;

&lt;p&gt;Component should respond to the amount of available pixels in its immediate container, not the overall viewport: this is component flow. For example &lt;code class=&quot;highlighter-rouge&quot;&gt;flex-row-wrap&lt;/code&gt; [should this be &lt;code class=&quot;highlighter-rouge&quot;&gt;flex-wrap&lt;/code&gt;?], &lt;code class=&quot;highlighter-rouge&quot;&gt;flex-grow&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;flex-shrink&lt;/code&gt;. Can combine this with CSS columns for powerful effect.&lt;/p&gt;

&lt;p&gt;Using &lt;code class=&quot;highlighter-rouge&quot;&gt;flex-basis: auto&lt;/code&gt; can get around many flexbox bugs (but check that its appropriate for your use case!).&lt;/p&gt;

&lt;p&gt;Can use flexbox-based pagination for carousel effect.&lt;/p&gt;

&lt;p&gt;Flexbox reversing can be used for timelines.&lt;/p&gt;

&lt;p&gt;Use &lt;code class=&quot;highlighter-rouge&quot;&gt;order&lt;/code&gt; for presentational content only. Don’t confuse the user!&lt;/p&gt;

&lt;p&gt;New: &lt;code class=&quot;highlighter-rouge&quot;&gt;display: contents&lt;/code&gt; replaces the element’s box with a pseudobox, and with the boxes of its childern. This means you can use it on a flex item that is itself a container for child items, and those child items become part of teh set of flex items in the grandparent flexbox container. (Experimental: https://developer.mozilla.org/en-US/docs/Web/CSS/display)&lt;/p&gt;

&lt;p&gt;To stop IE using flexbox, and force even those versions that support it (buggily), to ignore it, include the within a feature query:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@supports (display: flexbox) {
  display: flexbox;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;CSS grid: have a play.&lt;/p&gt;

&lt;p&gt;Can use new unit that comes with CSS grid module, &lt;code class=&quot;highlighter-rouge&quot;&gt;fr&lt;/code&gt;, to implement a peekaboo pattern.&lt;/p&gt;

&lt;h2 id=&quot;designing-the-future-of-content&quot;&gt;Designing the future of content&lt;/h2&gt;
&lt;p&gt;(Hannah Donovon @Han)
Worked at LastFM, This is my Jam, currently at Drip&lt;/p&gt;

&lt;p&gt;She designs for desires, not needs.&lt;/p&gt;

&lt;p&gt;Conent is not meaningful when to the user when it lacks context, connection or perspective. Future money will be in the thing around the content.&lt;/p&gt;

&lt;p&gt;Whether I know what I want, or whether I want something that I can’t define, I still need context, cononection and perspective. Knowing what I want is hard enough, so offering someone else a suggestion of  what they might want is a lot harder.&lt;/p&gt;

&lt;p&gt;Humans connect with us in ways that commputers can’t, e.g. taste.
Computers connect with us in ways that human’s can’t, e.g. providing global reach.&lt;/p&gt;

&lt;h3 class=&quot;no_toc&quot; id=&quot;context&quot;&gt;Context&lt;/h3&gt;

&lt;p&gt;Makes content meaningful.&lt;/p&gt;

&lt;p&gt;“Content is dumb until some smart designer grabs it and puts it somewhere with some context.” Paraphrasing Mark Bolton.&lt;/p&gt;

&lt;p&gt;You can use time and place to set context.&lt;/p&gt;

&lt;p&gt;At this is my jam, they scraped users’ YouTube avatar images (typically small and low res), cleaned them up, and applied some filters to make them look a bit funky, and applied them to a users’ (list/jam/profile/something), and so gave it some context.&lt;/p&gt;

&lt;h3 class=&quot;no_toc&quot; id=&quot;connection&quot;&gt;Connection&lt;/h3&gt;

&lt;p&gt;“The quality of connections is the key to quality per se” - Ray / Charles Eames.&lt;/p&gt;

&lt;p&gt;Familiarity can provide a connection, as can time and place.&lt;/p&gt;

&lt;p&gt;The best music recommendations come from friends.&lt;/p&gt;

&lt;h3 class=&quot;no_toc&quot; id=&quot;perspective&quot;&gt;Perspective&lt;/h3&gt;

&lt;p&gt;Gives content feeling.&lt;/p&gt;

&lt;p&gt;Gives the ablility to give a damn. Computers can’t give a damn.&lt;/p&gt;

&lt;p&gt;The story can provide perspective, as can ethos.&lt;/p&gt;

&lt;p&gt;“Designers solve problems, but so do many other occupations. What designers actually do is create culture” - paraphrasing Jack Schultz.&lt;/p&gt;

&lt;p&gt;Unfortunatley at the moment it can feel like everything looks the same. See &lt;a href=&quot;https://louderthanten.com/articles/story/design-machines&quot;&gt;Design machines&lt;/a&gt;, and the parody &lt;a href=&quot;http://adventurega.me/bootstrap/&quot;&gt;HEY LOOK, IT’S EVERY BOOTSTRAP WEBSITE EVER&lt;/a&gt;. As designers we can do better!&lt;/p&gt;

&lt;h2 id=&quot;devtools-an-animated-journey&quot;&gt;Devtools, an animated journey&lt;/h2&gt;
&lt;p&gt;(Umar Hansa @umaar)&lt;/p&gt;

&lt;p&gt;Member of the Google Developer Expert Programme.&lt;/p&gt;

&lt;p&gt;Produces &lt;a href=&quot;umaar.com/dev-tips&quot;&gt;weekly newsletter of devtool tips in animated gif form&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Has written posts on SCSS source maps.&lt;/p&gt;

&lt;h3 class=&quot;no_toc&quot; id=&quot;resources&quot;&gt;Resources&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Google’s &lt;a href=&quot;https://developer.chrome.com/devtools&quot;&gt;Devtools reference&lt;/a&gt;, doesn’t include everything experimental as moving so fast.&lt;/li&gt;
  &lt;li&gt;If you want to track devtools bugs or contribute, checkout the &lt;a href=&quot;https://developer.chrome.com/devtools/docs/contributing&quot;&gt;contributing page&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://discover-devtools.codeschool.com/&quot;&gt;discover-devtools.codeschool.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;His examples need experimental devtools features activated in Chrome Canary &lt;code class=&quot;highlighter-rouge&quot;&gt;chrome://flags&lt;/code&gt;, and the appropriate experiment enabled within devtools preferences.&lt;/p&gt;

&lt;p&gt;If you want to make every new tab / window open with a devtools window ready-attached, start Chrome from the command line with the flag &lt;code class=&quot;highlighter-rouge&quot;&gt;auto-open-devtools-for-tabs&lt;/code&gt;.&lt;/p&gt;

&lt;h3 class=&quot;no_toc&quot; id=&quot;elements-panel&quot;&gt;Elements panel&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;toggle class&lt;/li&gt;
  &lt;li&gt;layout editor (still work in progress). To activate it, within devtools preferences, press &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;shift&amp;gt;&lt;/code&gt; 6 times to expose the WIP features, then check “Layout editor”, and restart).&lt;/li&gt;
  &lt;li&gt;Hitting &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;esc&amp;gt;&lt;/code&gt; to bring up the console gives not just console tab, but also a promises tab and animation inspector. It has some Web animations API integration (I missed what), and keyframe editing.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class=&quot;no_toc&quot; id=&quot;network-panel&quot;&gt;Network panel&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Request blocking, can e.g. block css load to see how your site behaves if the css load borks.&lt;/li&gt;
  &lt;li&gt;connection throttling&lt;/li&gt;
  &lt;li&gt;filmstrip of page load&lt;/li&gt;
  &lt;li&gt;may search network requests with the &lt;code class=&quot;highlighter-rouge&quot;&gt;domain:&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;mixed-content&lt;/code&gt; prefixes. V useful, especially if you’re migrating to TLS and want to catch any http-loaded assets.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class=&quot;no_toc&quot; id=&quot;sources-pane&quot;&gt;Sources pane&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Click on DOM element then go to Event Listeners pane to see what listeners are registered to this element.&lt;/li&gt;
  &lt;li&gt;can live edit js. (This is an achievement!)&lt;/li&gt;
  &lt;li&gt;can blackbox scripts so they’re not listed nor exposed when debugging (they still run as usual).&lt;/li&gt;
  &lt;li&gt;supports js source maps&lt;/li&gt;
  &lt;li&gt;can use devtools for persistent authoring using &lt;a href=&quot;https://developer.chrome.com/devtools/docs/workspaces&quot;&gt;workspaces&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;can inspect service workers and see what’s in their cached storage&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class=&quot;no_toc&quot; id=&quot;timeline&quot;&gt;Timeline&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;cpu throttling!&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class=&quot;no_toc&quot; id=&quot;accessibility&quot;&gt;Accessibility&lt;/h3&gt;

&lt;p&gt;Accessibility tools for Chrome are currently provided by a plugin, but  natve a11y tooling is on its way.&lt;/p&gt;

&lt;h2 id=&quot;overthinking-design-and-embracing-minutiae&quot;&gt;Overthinking design and embracing minutiae&lt;/h2&gt;
&lt;p&gt;(Jon Setzen @jonsetzen)&lt;/p&gt;

&lt;p&gt;Works at MediaTemple.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;US ecomomy is 84% service economy&lt;/li&gt;
  &lt;li&gt;organisations generally spend 20x more on marketing than they do on ‘experience’&lt;/li&gt;
  &lt;li&gt;customers who’ve had a good experience buy 140% more than those that haven’t&lt;/li&gt;
  &lt;li&gt;defines good service as useable / efficient / desireable&lt;/li&gt;
  &lt;li&gt;We tend to only think about service when it’s bad&lt;/li&gt;
  &lt;li&gt;where in your user experience do you start to think about your users’ experience (think airline).&lt;/li&gt;
  &lt;li&gt;[talked about Uber Eats]&lt;/li&gt;
  &lt;li&gt;MediaTemple Wordpress provisioning can take a while, have developed a game you can play while you’re waiting.&lt;/li&gt;
  &lt;li&gt;A bad experience degrades trust (see Mark Bolton’s point on gradual degredation).&lt;/li&gt;
  &lt;li&gt;unhappy users are expensive&lt;/li&gt;
  &lt;li&gt;Book: &lt;a href=&quot;http://thisisservicedesignthinking.com/&quot;&gt;This is Service Design Thinking&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;living-design-systems&quot;&gt;Living Design Systems&lt;/h2&gt;
&lt;p&gt;(Jina Bolton @jina)&lt;/p&gt;

&lt;p&gt;Works at Salesforce UX. As much as they can they open source: &lt;a href=&quot;https://github.com/salesforce-ux&quot;&gt;github.com/salesforce-ux&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;They build tools that other business will use to build things.&lt;/li&gt;
  &lt;li&gt;They design for configuration.&lt;/li&gt;
  &lt;li&gt;A fractured process leads to a fractured user experience&lt;/li&gt;
  &lt;li&gt;A great design system is useable by the entire team&lt;/li&gt;
  &lt;li&gt;design system is a product, not a project&lt;/li&gt;
  &lt;li&gt;drive design decisions with prioritised design principles&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Their design goals are:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;clarity&lt;/li&gt;
  &lt;li&gt;efficiency&lt;/li&gt;
  &lt;li&gt;consistency&lt;/li&gt;
  &lt;li&gt;beauty&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Their first step: a UI Inventory - take &lt;em&gt;a lot&lt;/em&gt; of notes! Document as much as you can: states, responsiveness, a11y, and also record open questions so you can come back to them later.&lt;/p&gt;

&lt;p&gt;Make a list of people involved and their responsibilities.&lt;/p&gt;

&lt;p&gt;[Sounds like a more design-focused version of our kickoff: project canvas + tech kickoff.]&lt;/p&gt;

&lt;p&gt;BIG QUESTION: How to maintain consistency over a large organisation?&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Store your assets in a repo. Once they’re updated, automatically update into styleguide and website&lt;/li&gt;
  &lt;li&gt;They use the concept of design tokens for e.g. font-size, colour etc. Abstraction of CSS properties into a token system that can deliver that configuration to not only the website and the pattern library, but the Android app team, the iOS app team, etc. All the different technical systems get the result of the design token in the appropriate format for them: e.g. hex for web, 8-character hex rgba value for Android, etc etc. Think SASS vriables, but cross-technology. Nothing is now hardcoded, the design tokens are framework agnostic and enable one central change to cascade to each of the technology stacks that need it.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;they open sourced the tool they use to generate the configuration from the design tokens: &lt;a href=&quot;https://github.com/salesforce-ux/theo&quot;&gt;theo&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Clarity beats brevity: they use BEM naming.&lt;/li&gt;
  &lt;li&gt;Additionally they namespace their blocknames to ensure to avoid potential clashes with a Salesforce client’s code, e.g. &lt;code class=&quot;highlighter-rouge&quot;&gt;slds-button&lt;/code&gt;, rather than just &lt;code class=&quot;highlighter-rouge&quot;&gt;button&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;They also wrap their components in a div with a namespace class to provide namespace isolation to any css that they write to make sure they don’t accidentally stomp on client’s stying, for example they’ll use the CSS rule &lt;code class=&quot;highlighter-rouge&quot;&gt;.slds .slds-form&lt;/code&gt; to address:&lt;/li&gt;
&lt;/ul&gt;

&lt;pre&gt;&lt;code class=&quot;language-HTML&quot;&gt;&amp;lt;div class=&quot;slds&quot;&amp;gt;
  &amp;lt;form class=&quot;slds-form&quot;...&amp;gt;
    ...
  &amp;lt;/form&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A styleguide should show all states of a component, otherwise those states will get overlooked.&lt;/p&gt;

&lt;p&gt;Typography system: they created text utility classes decoupled from components (also see Alla’s talk).&lt;/p&gt;

&lt;p&gt;Only show the code in the styleguide that the people need to see, and don’t build it until you need it!&lt;/p&gt;

&lt;p&gt;Using this system leads to better communication and better prototypes - no more proliferation of onconsistent styles.&lt;/p&gt;

&lt;p&gt;They have design ofice hours, and CSS office hours where anyone can drop in to consult with them on design or CSS.&lt;/p&gt;

&lt;p&gt;Recommends Nathan Curtis, he’s has written &amp;amp; spoken a lot about design systems:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Difference between a styleguide and a design system: “A style guide is an artifact of design process. A design system is a living, funded product with a roadmap &amp;amp; backlog, serving an ecosystem.” - Nathan Curtis (https://twitter.com/nathanacurtis/status/656829204235972608)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://medium.com/eightshapes-llc/a-design-system-isn-t-a-project-it-s-a-product-serving-products-74dcfffef935#.txjgrr4hv&quot;&gt;on medium&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://www.uie.com/brainsparks/2015/09/09/nathan-curtis-building-scalable-design-systems-and-style-guides/&quot;&gt;podcast with Jared Spool&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;styleguides.io/podcast/nathan-curtis/&quot;&gt;styleguides.io podcast&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;compare &lt;a href=&quot;https://medium.com/eightshapes-llc/team-models-for-scaling-a-design-system-2cf9d03be6a0&quot;&gt;Team Models for Scaling a Design System&lt;/a&gt; with &lt;a href=&quot;https://medium.com/salesforce-ux/the-salesforce-team-model-for-scaling-a-design-system-d89c2a2d404b#.hcv0k3dje&quot;&gt;The Salesforce Team Model for Scaling a Design System&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://blog.capwatkins.com/the-sliding-scale-of-giving-a-fuck&quot;&gt;blog.capwatkins.com/the-sliding-scale-of-giving-a-fuck&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;modern-workflow-and-tooling&quot;&gt;Modern workflow and tooling&lt;/h2&gt;
&lt;p&gt;(Wes Bos @wesbos)&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://reactforbeginners.com&quot;&gt;reactforbeginners.com&lt;/a&gt;
&lt;a href=&quot;http://sublimetextbook.com&quot;&gt;sublimetextbook.com&lt;/a&gt;
&lt;a href=&quot;http://commandlinepoweruser.com&quot;&gt;commandlinepoweruser.com&lt;/a&gt;
&lt;a href=&quot;http://flexbox.io&quot;&gt;flexbox.io&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There’s a fine line between tooling for its own sake and gettign stuff done.&lt;/p&gt;

&lt;h3 class=&quot;no_toc&quot; id=&quot;build-tools&quot;&gt;Build tools&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;47% use Gulp. 20% said they used no build tools.&lt;/li&gt;
  &lt;li&gt;can use for many things, e.g.: critical CSS, removing unused CSS (purify), minifying images, uglifying code… you name it…&lt;/li&gt;
  &lt;li&gt;npm scripts are great for the simple things, but can get nasty when the complexity increases only a little.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Webpack: “Gulp meets Browserify”. Powerful but have to learn API.&lt;/p&gt;

&lt;h3 class=&quot;no_toc&quot; id=&quot;dependency-management-modules--&quot;&gt;Dependency management (Modules! :-))&lt;/h3&gt;

&lt;p&gt;To get code authored as modules working in the browser, you can use browserify, webpack or jspm. When authoring, try to use ES6 module syntax if you can, because that’s what it will be eventually anyway.&lt;/p&gt;

&lt;p&gt;There are 2 main registries for modules: bower and npm (jspm sits on top of npm). npm has nested dependencies, whereas Bower has a flat hierarchy. Prefer npm over Bower if you can.&lt;/p&gt;

&lt;p&gt;Ecosystems is coming soon to npm to enable non-hierarchical grouping.&lt;/p&gt;

&lt;p&gt;Babel transpiles to ES5 for the browser.&lt;/p&gt;

&lt;p&gt;CSSNext is like Babel for CSS Level 4 modules (and is part of the PostCSS ecosystem).&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.browsersync.io/&quot;&gt;browsersync&lt;/a&gt; comes with built in certificate so can check things that need TLS on localhost. Can also proxy existing apps/servers.&lt;/p&gt;

&lt;p&gt;sourcemaps are treasuremaps for bugs.&lt;/p&gt;

&lt;h2 id=&quot;improving-screen-legibibilty&quot;&gt;Improving screen legibibilty&lt;/h2&gt;
&lt;p&gt;(Tobias Frere-Jones @frerejones)&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Sub-pixel rendering is handled differently by different browsers.&lt;/li&gt;
  &lt;li&gt;Helvetica subpixel rendering is generally poor, parallel lines blend into each othe.&lt;/li&gt;
  &lt;li&gt;Upper and lower case look similar&lt;/li&gt;
  &lt;li&gt;lower case “o” and lower case “c” look very similar&lt;/li&gt;
  &lt;li&gt;typefaces drawn specifically for the web are better, and generally have generaous spacing between letters, and wide appetures.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hinting - distorts the outline to create a more pleasing shape, e.g helps with separating the dot of tyhe ‘i’ from its stem.&lt;/p&gt;

&lt;p&gt;CBS in 1967 noticed terrible rendering of fonts on the TV screen e.g. on map labels: there was a lot of blur and bloom. They fixed some of the problem, but in the process, moved away from the previous News Gothic, more towards Helvetica so they didn’t solve all of the problems. (Helvetica was really poopular at the time: this choice sounds like a stylistic rule - see Alla’s talk.&lt;/p&gt;

&lt;p&gt;Metal type faces are slightly different at different sizes because they can be (being physical blocks of metal). Because of this, 6pt running copy in century-old newspapers still reads fine.&lt;/p&gt;

&lt;p&gt;“Screen text can be treated as an optical size” - he tried this with his new face: Mallory, that came out last year: it’s got “Standard” and “Microplus” versions, the latter being for the web and tiny print.&lt;/p&gt;

&lt;p&gt;Fonts can and should be equally relavent everywhere, not just on screen, not just on printed material.&lt;/p&gt;

&lt;p&gt;A prerequisite for good design is clear intention.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;(&lt;a href=&quot;/2016/03/18/smashing-conference-2016-day-1/&quot;&gt;Find out what happened on day 1&lt;/a&gt;.)&lt;/p&gt;
</description>
        <pubDate>Fri, 18 Mar 2016 15:40:00 +0000</pubDate>
        <link>http://decodeuri.net/2016/03/18/smashing-conference-2016-day-2/</link>
        <guid isPermaLink="true">http://decodeuri.net/2016/03/18/smashing-conference-2016-day-2/</guid>
        
        
      </item>
    
      <item>
        <title>Smashingconf 2016: day 1</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#building-great-design-teams&quot; id=&quot;markdown-toc-building-great-design-teams&quot;&gt;Building great design teams&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#building-a-pattern-language-for-the-web&quot; id=&quot;markdown-toc-building-a-pattern-language-for-the-web&quot;&gt;Building a pattern language for the web&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#svg-in-motion&quot; id=&quot;markdown-toc-svg-in-motion&quot;&gt;SVG in motion&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#http2&quot; id=&quot;markdown-toc-http2&quot;&gt;HTTP/2&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#understanding-people&quot; id=&quot;markdown-toc-understanding-people&quot;&gt;Understanding people&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#dirty-front-end-tricks&quot; id=&quot;markdown-toc-dirty-front-end-tricks&quot;&gt;Dirty front end tricks&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#look-no-media-queries&quot; id=&quot;markdown-toc-look-no-media-queries&quot;&gt;Look, no media queries!&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#join-the-dots&quot; id=&quot;markdown-toc-join-the-dots&quot;&gt;Join the dots&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#addendum&quot; id=&quot;markdown-toc-addendum&quot;&gt;Addendum&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(&lt;a href=&quot;/2016/03/18/smashing-conference-2016-day-2/&quot;&gt;Find out what happened on day 2&lt;/a&gt;.)&lt;/p&gt;

&lt;h2 id=&quot;building-great-design-teams&quot;&gt;Building great design teams&lt;/h2&gt;
&lt;p&gt;(Aarron Walter @aarron)&lt;/p&gt;

&lt;p&gt;Until recently design lead at MailChimp, now freelance.&lt;/p&gt;

&lt;p&gt;Often lose details when handing over between research, design and development, as handover can be clunky. Having integrated research / design / development teams increases empathy which helps with handover, but also makes handover less waterfall.&lt;/p&gt;

&lt;p&gt;Difference between art and design: design is about service. Need to research the context for the service delivery of your design. It’s hard to see the future of your product, but if you can talk to users and find where they’re working around your product to get what they need done, that can give you an idea of what your product is missing.&lt;/p&gt;

&lt;p&gt;Successful product companies perform onstant quality improvements to existing products, as well as developing new things.&lt;/p&gt;

&lt;p&gt;On site research will give you more context, e.g. age of tech, level of distraction, quality of lighting etc etc, all have a potential effect on how youe user interacts with your product. If you can video your users and play back to colleagues, more people in your company can appreciate your users’ contexts.&lt;/p&gt;

&lt;p&gt;Before MailChimp was cross-device, he made a video (resourced in-house), of a future user who integrates multi device access into her use of MailChimp. More effective at communicating the story of a user of a future version of their product than expecting everyone to read and digest a 30 page report on future product direction.&lt;/p&gt;

&lt;p&gt;Agile, used blindly, can lead to painful forcing of process as waterfall did. Reasrch, design and development naturally work at different cadences, development is generally very suitable for scrum, but design works on a longer iteration cycle, and research longer still. Also, research should generally have a head start over design, and design likewise over development.&lt;/p&gt;

&lt;p&gt;Deadlines provide powerful focus.&lt;/p&gt;

&lt;p&gt;Small, integrated interdisciplinary teams are very powerful.&lt;/p&gt;

&lt;p&gt;In teams, people are the hardest part. So, hiring:&lt;/p&gt;

&lt;p&gt;The process is often broken, often hiring is done based on ticking off a list, not matching the person to fit the team. He believes in getting the right person and training them up (a bit) / coaching, if necessary, rather than hiring a checklist-satisfying candidate who doesn’t fit well into the team.&lt;/p&gt;

&lt;p&gt;People are more often fired for soft skill problems than core competency problems. [His assertion.] His hiring process:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;initial phone screen as a sanity check&lt;/li&gt;
  &lt;li&gt;followup call to get to know the candidate a bit: aspirations and interests, etc&lt;/li&gt;
  &lt;li&gt;1 day imersion into the team, see how they fit in, how the team takes to them [is the person paid? is the time flexible? how do they accommodate people who are currently working, into that framework?]&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;People will be best motivated if they share your goals, so hire people who believe what you believe [but don’t start a cult?]. &lt;em&gt;BUT&lt;/em&gt; if you want diversity of thought, you need to bring in people with diverse experience. Needed be a contradiction, but be mindful.&lt;/p&gt;

&lt;p&gt;Hire people who are smarter than you.&lt;/p&gt;

&lt;p&gt;Hire humility: humility aids effective collaboration.&lt;/p&gt;

&lt;p&gt;Staff 1:1: (you can often tell when a deadline’s about to be missed from what’s said, and how, here, he finds conflict is the usual reason). You can take that time with staff to acknowledge where they’re great, but also make sure they know where their weaknesses are (but maybe put it better than that). Important for people to know their own weaknesses, because humility: then they know when to hand over to someone’s who’s better at that particular thing.&lt;/p&gt;

&lt;p&gt;Acknoweldge when you’re wrong. As a desgin leader: “My job is not to know more about everything, my job is to be more curious about everything.”&lt;/p&gt;

&lt;h2 id=&quot;building-a-pattern-language-for-the-web&quot;&gt;Building a pattern language for the web&lt;/h2&gt;
&lt;p&gt;Alla Kholmalova (@craftui)&lt;/p&gt;

&lt;p&gt;Recommended book Thinking in Systems&lt;/p&gt;

&lt;p&gt;System: interconnected elements with a purpose, more than just a collection of elements.&lt;/p&gt;

&lt;p&gt;Purpose of a design system? Provide some coherent patterns to facilitate and encourage certain types of behaviour.&lt;/p&gt;

&lt;p&gt;Types of behaviour: semantic, structural, visual, behavioural.&lt;/p&gt;

&lt;h3 class=&quot;no_toc&quot; id=&quot;semantic&quot;&gt;Semantic&lt;/h3&gt;
&lt;p&gt;See Language of Modular Design on A List Apart.&lt;/p&gt;

&lt;p&gt;Name things based on the function of that thing in the global system, not its function on an individual page.&lt;/p&gt;

&lt;p&gt;Useful to print out UI to distill global functions &amp;amp; name things accordingly (sounds like our naming exercise).&lt;/p&gt;

&lt;h3 class=&quot;no_toc&quot; id=&quot;structural&quot;&gt;Structural&lt;/h3&gt;
&lt;p&gt;e.g. atomic design.&lt;/p&gt;

&lt;p&gt;They were strict, in hindsight realise they should have adapted more.&lt;/p&gt;

&lt;p&gt;A big grey area for them was distinguishing between molecules and organisms. Followed Brad Frost’s advice [check to recapitulate]. Lead to long debates.&lt;/p&gt;

&lt;p&gt;After 18 months held a workshop where split into several groups with printouts of all the components and asked to group. There was &lt;em&gt;no consensus&lt;/em&gt; still as to which were molecules and which were organisms.&lt;/p&gt;

&lt;p&gt;They &lt;em&gt;did&lt;/em&gt; find common ground identifying some compeonents as ‘standalones’, and some as ‘helpers’. Standalones being well defined, independent parts of a page, helpers don’t work out of context, but provide help to other components. Identifying this way, they mapped helpers to molecules and standalones to organisms.&lt;/p&gt;

&lt;h3 class=&quot;no_toc&quot; id=&quot;visual&quot;&gt;Visual&lt;/h3&gt;
&lt;p&gt;What about style properties that are applied to atoms? In this model do they become sub-atomic particles? Clearly this abstraction is in danger of getting out of control.&lt;/p&gt;

&lt;p&gt;Visual patterns cut across the semantics. [This is what I was trying to describe a while ago for our pattern library.]&lt;/p&gt;

&lt;h4 class=&quot;no_toc&quot; id=&quot;relationships-1&quot;&gt;Relationships 1&lt;/h4&gt;
&lt;p&gt;Relationships between modules can make picking typographic size &amp;amp; spacing difficult, as the context of a module’s use can affect what works, and  that context is not part of the module, it’s operating above of/outside it.&lt;/p&gt;

&lt;p&gt;[not sure of my notes at this next bit]
&lt;em&gt;Visual&lt;/em&gt; modules are of 3 types: global function, typographic style, or spacing. Treat core brand prpoerties separately, don’t mix them with modules. [Good use case for Sass aviables here.]&lt;/p&gt;

&lt;p&gt;Define not just elements, but the relationship between them.&lt;/p&gt;

&lt;p&gt;A design pattern must be connected to human behaviour: if it looks like a pattern, but it lacks that connection, then it’s just a stylistic rule (something that might be trendy, but adds nothing to aid the desired behaviour for the component - see National Library of France, Paris(?)).&lt;/p&gt;

&lt;p&gt;Watch for red flags (she only one example), e.g. modules that have the same behaviour but that look different.&lt;/p&gt;

&lt;p&gt;Evolving a design system is gradual, piecemeal, and can be messy, not the result of a grand plan (assume this refers to deriving patterns from existing setup rather than a new build).&lt;/p&gt;

&lt;h3 class=&quot;no_toc&quot; id=&quot;investigate&quot;&gt;Investigate&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;Tom Osbourne: Visual loudness guide&lt;/li&gt;
  &lt;li&gt;Design tokens: Salesforce&lt;/li&gt;
  &lt;li&gt;Brad Frost’s advice to distinguishing between molecules and organisms&lt;/li&gt;
  &lt;li&gt;stylistic rules&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;svg-in-motion&quot;&gt;SVG in motion&lt;/h2&gt;
&lt;p&gt;(Sara Soueidan @sarasoueidan)&lt;/p&gt;

&lt;p&gt;Which embedding mechanism to use? Depends on the answers to the questions:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;is it animated?&lt;/li&gt;
  &lt;li&gt;is it interactive?&lt;/li&gt;
  &lt;li&gt;does animation use css or js?&lt;/li&gt;
  &lt;li&gt;what’s the browser support for the animation?&lt;/li&gt;
  &lt;li&gt;what’s the required fallback(, and what’s the browser support for that)?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;object&amp;gt;&lt;/code&gt; embedding mechanism her favourite, it allows for good fallback mechanisms: for example the tabular data from which an SVG infographic is derived:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;object ...&amp;gt;
  &amp;lt;!-- fallback --&amp;gt;
&amp;lt;/object&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To get at the SVG DOM from an SVG loaded by &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;object&amp;gt;&lt;/code&gt;, use &lt;code class=&quot;highlighter-rouge&quot;&gt;[object_el].contentDocument&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Don’t optimise after setting up animations: they will almost certainly break.&lt;/p&gt;

&lt;p&gt;Should you animate with css or do you need js?&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;transformations: js&lt;/li&gt;
  &lt;li&gt;path morphing: js&lt;/li&gt;
  &lt;li&gt;line drawing: js&lt;/li&gt;
  &lt;li&gt;colour and simple animations/transitions: css&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Only some presentation attributes are also represented as css properties and so can be addresssed in CSS, and therefore potentially animatable.&lt;/p&gt;

&lt;p&gt;Default transform origin for HTML DOM element is 50% 50% into the elemen (centre).&lt;/p&gt;

&lt;p&gt;Default transform origin for SVG element is the origin of the SVG viewport (top left corner of the whole SVG element as displayed).&lt;/p&gt;

&lt;p&gt;When setting &lt;code class=&quot;highlighter-rouge&quot;&gt;transform-origin&lt;/code&gt; on an SVG element:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;using &lt;code class=&quot;highlighter-rouge&quot;&gt;%&lt;/code&gt; is relative to the bounding box of the element, including its stroke.&lt;/li&gt;
  &lt;li&gt;using &lt;code class=&quot;highlighter-rouge&quot;&gt;px&lt;/code&gt; is relative to the SVG canvas&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;SVG animations do not run on the GPU, and so performance sucks.&lt;/p&gt;

&lt;p&gt;SVG has 2 coordinate systems, the viewport and the view box. See:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;https://sarasoueidan.com/blog/svg-coordinate-systems/&lt;/li&gt;
  &lt;li&gt;https://sarasoueidan.com/demos/interactive-svg-coordinate-system/index.html&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;http2&quot;&gt;HTTP/2&lt;/h2&gt;
&lt;p&gt;(Partick Hamann @patrickhamann)&lt;/p&gt;

&lt;p&gt;Works at FT.&lt;/p&gt;

&lt;p&gt;Slides at https://speakerdeck.com/patrickhamann/http2-what-where-why-and-when-smashing-conference-march-2016&lt;/p&gt;

&lt;p&gt;2016:
Median # requests per page: 80
95th-percentile # requests per page: 200-300&lt;/p&gt;

&lt;p&gt;1995:
1-5 requests per page&lt;/p&gt;

&lt;p&gt;Average UK 3G connection takes about 600-1000ms fir DNS/TCP/TLS negotiation.&lt;/p&gt;

&lt;p&gt;Head of line blocking means you can’t parallel request on the same connection becsuse there’s no way of telling when one request ends and another starts. Browsers got around this by opening up a brand new connection in parallel for the addtional requests. Latest pre-HTTP/2 spec allows for up to 10 concurrent connections (was 6, before then it was 4).&lt;/p&gt;

&lt;p&gt;When even 6 connections aren’t enough, there’s always domain sharding.&lt;/p&gt;

&lt;p&gt;So as developers we concatonate our css  &amp;amp; js files to reduce the number of requests.&lt;/p&gt;

&lt;p&gt;But we might only need 1 line from a huge JavaScript file. It’s a similar case with image spriting.&lt;/p&gt;

&lt;p&gt;We inline critical CSS, but even this technique to improve performance render performance has performance hits as well as benefits (e.g. not cacheable - anything else?)&lt;/p&gt;

&lt;p&gt;HTTP/2 invented, based heavily on Google’s SPDY (2006), to speed up delivery over high latency connections.&lt;/p&gt;

&lt;p&gt;The heart of an HTTP/2 connection is a stream. A stream comprises binary data frames that declare how long they are, and carry a stream identifier. The frame’s stream identifier means that frames for different streams may be interleaved and reassembled correctly in the browser.&lt;/p&gt;

&lt;p&gt;There’s a prioritisation system to organise which resources are requested when. Each stream has a weight which the client can send to the server, so the server can decide the order to send things back in. Weights can be changed when the browser comes across something that changes the priorities.&lt;/p&gt;

&lt;p&gt;HPACK: header compression. Begins to build state between the client and the server.&lt;/p&gt;

&lt;p&gt;Server push can pre-empt client request by sending resource before the client asks for it. For example the server receives a request for an HTML page. If the server knows that the client will request the css next, &lt;em&gt;before any of the html is sent&lt;/em&gt;, the server sends the CSS file to the client. Note that this must happen before the HTML itself is sent, in order to avoid possible race conditions where parsing the HTML might also trigger a request for the CSS file.&lt;/p&gt;

&lt;p&gt;Reasonable browser support: http://caniuse.com/#search=http2&lt;/p&gt;

&lt;p&gt;Sounds like the requirement for TLS is actually a hack. SPDY devs found packets were being dropped at switches and routers that didn’t understand the new protocol [anti-malware got confused?], so sent data over TLS which the middleware was fine with. Spec doesn’t mandate TLS, but every implementation has it as a hard requirement.&lt;/p&gt;

&lt;p&gt;If looking for a server for use with HTTP/2, ask about:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;support for stream priorities&lt;/li&gt;
  &lt;li&gt;support for server push&lt;/li&gt;
  &lt;li&gt;strategies for resource hinting&lt;/li&gt;
  &lt;li&gt;whether they provide any intelligent optimsisation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Easingn in the implementation:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;CDN first&lt;/li&gt;
  &lt;li&gt;then take a reverse proxy approach&lt;/li&gt;
  &lt;li&gt;finally HTTP/2 AllTheThings&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Don’t overdo it with server push: only push critical assets like core js, critical css and maybe fonts.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;Link&lt;/code&gt; HTTP header is like &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;link&amp;gt;&lt;/code&gt;. Means could use &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;link rel=&quot;preload&quot;&amp;gt;&lt;/code&gt; &lt;em&gt;but&lt;/em&gt; Yoav Weiss who implemented preload in Blink advises against it as it uses completely different semantics from push.&lt;/p&gt;

&lt;p&gt;[Track intelligent push].&lt;/p&gt;

&lt;p&gt;Look at connection view in dev tools. It’s pretty bare of meaningful metrics. Remember headers are now binary so harder to inspect. Jim Shaver has a post on setting up Wireshark to inspect HTTP/2 requests (is it this one: &lt;a href=&quot;https://jimshaver.net/2015/02/11/decrypting-tls-browser-traffic-with-wireshark-the-easy-way/&quot;&gt;jimshaver.net/2015/02/11/decrypting-tls-browser-traffic-with-wireshark-the-easy-way&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Rebecca Murphy has a tool to inspect HTTP/2 logs.&lt;/p&gt;

&lt;p&gt;Generally though, HTTP/2 tooling is in a pretty poor state at the moment.&lt;/p&gt;

&lt;h3 class=&quot;no_toc&quot; id=&quot;when-to-switch&quot;&gt;When to switch?&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;Go TLS first. It’s a prerequisite anyway, and this way you’ll iron out the TLS wrinkles before you hit the HTTP/2 wrinkles.&lt;/li&gt;
  &lt;li&gt;Then check the client support for it in your user base&lt;/li&gt;
  &lt;li&gt;Change your workflow to be HTTP/2 first&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Perf basics are still very important!&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;FT’s experience:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;5s improved download speed on mobile and tablet.&lt;/li&gt;
  &lt;li&gt;start render event brought forward by 500ms.&lt;/li&gt;
  &lt;li&gt;not much change on desktop&lt;/li&gt;
  &lt;li&gt;this is expected as HTTP/2 design goal is to improve performance on high latency networks, which you’d expect mobile and tablet to have much more use of.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think about grouping files based on frequency of change.&lt;/p&gt;

&lt;p&gt;Also, because GZIP gets better when sending more data, sending many small files may end up sending a lot more data than sending down a single GZIP’d file - see &lt;a href=&quot;http://engineering.khanacademy.org/posts/js-packaging-http2.htm&quot;&gt;Kahn Academy’s experience&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;understanding-people&quot;&gt;Understanding people&lt;/h2&gt;
&lt;p&gt;(Chris Shiflett @shiflett)&lt;/p&gt;

&lt;p&gt;Perception &amp;gt; reality e.g. to make something appear visually centered, it may have to actually be moved off centre by a few pixels.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.luckyironfish.com/&quot;&gt;Lucky iron fish&lt;/a&gt; only worked when it was made into a fish. The original hunks of iron were not adopted as people didn’t want to put it in their cooking pot.&lt;/p&gt;

&lt;h3 class=&quot;no_toc&quot; id=&quot;change-blindness&quot;&gt;Change blindness&lt;/h3&gt;

&lt;p&gt;Showed a photo, showed a white screen for a few seconds, then showed the same photo again with one small detail changed. Very hard to notice the difference. It’s like this for users when they make a mistake filling in a form, the page posts to the server (white screen), then the form comes back looking very similar but with an error message added. The closer the error-state form looked like the original, the harder it is for users to spot the error state message and realise there’s a problem. Here, inconsistencey can be a good thing.&lt;/p&gt;

&lt;p&gt;Users aren’t stupid, they’re human.&lt;/p&gt;

&lt;p&gt;Tokyo subway uses ambient signifiers: each train line/station comination has a unique set of chimes so you don’t need to see out of the window to know which stop you’re at (once you’ve learned the chimes). For regular commuters, the anticipation established with this means that they pick up very quickly if something’s gone awry, for example they fell asleep, have just woken up and notice the chimes are wrong - they’ve gone past their stop!&lt;/p&gt;

&lt;p&gt;Think songs in a playlist: if you hear a playlist song somewhere else, you’re expecting the next song on your playlist to come on next, and when it doesn’t it can jar.&lt;/p&gt;

&lt;p&gt;Decoys: a pricing option that the designer doesn’t expect to be chosen, but that is likely to affect the option that you do choose. Gaps between the price points can affect which options people choose, too.&lt;/p&gt;

&lt;p&gt;Beware dark patterns: these are deliberately designed to trick people.&lt;/p&gt;

&lt;p&gt;Mony Hall problem: 3 doors, 2 goats, one car. Pick a door, don’t open it. I show you a different door with a goat. Do you stick with your original choice or switch to the other door? Always switch for the best chance of getting the car.&lt;/p&gt;

&lt;p&gt;Disruption. Ugh, no. Don’t try to abruptly change your users’ behaviour. Better to understand and shape it instead.&lt;/p&gt;

&lt;h2 id=&quot;dirty-front-end-tricks&quot;&gt;Dirty front end tricks&lt;/h2&gt;
&lt;p&gt;(Vitaly Friedman @smashingmag)&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;To nest links(!), place the inner one inside an &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;object&amp;gt;&lt;/code&gt; element. Won’t work in IE8 as it doesn’t support &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;object&amp;gt;&lt;/code&gt; but there are workarounds(?)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://css-tricks.com/simple-css-row-column-highlighting/&quot;&gt;Highlihghting the row and column of a cell in a table&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;To get uniform padding on an inline element that’s wrapping due to the length of its content (so the padding is not just at the beginning of the first line and the end of the last, but applies as a gutter on either side of the inline element’s content), use horizontal (only) box shadow, or &lt;a href=&quot;http://caniuse.com/#search=box-decoration-break&quot;&gt;box-decoration-break&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Fab four technique for responsive layout in email without floats or media queries: 
&lt;a href=&quot;https://medium.freecodecamp.com/the-fab-four-technique-to-create-responsive-emails-without-media-queries-baf11fdfa848&quot;&gt;https://medium.freecodecamp.com/the-fab-four-technique-to-create-responsive-emails-without-media-queries-baf11fdfa848&lt;/a&gt;
&lt;a href=&quot;http://responsiveemailpatterns.com/&quot;&gt;http://responsiveemailpatterns.com/&lt;/a&gt;. This uses &lt;code class=&quot;highlighter-rouge&quot;&gt;calc()&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;width&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;min-width&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;max-width&lt;/code&gt; and is a work of twisted genius.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;To wrap very long words (URLs, sequences), use a combination of &lt;code class=&quot;highlighter-rouge&quot;&gt;word-wrap&lt;/code&gt; and overflow wrap.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Jake Archibald on loading CSS&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;table-layout: fixed&lt;/code&gt; fixes table column widths based on the width of their first row. This is fine as long as the first row contains the longest content…&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;object-fit&lt;/code&gt; is to content images what &lt;code class=&quot;highlighter-rouge&quot;&gt;background-size&lt;/code&gt; is to background images.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://www.carlsberg.co.uk/&quot;&gt;Carlsberg&lt;/a&gt; age selector a good example of a redesigned selector.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://baymard.com/labs/country-selector&quot;&gt;Redesigning the country selector&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Interesting &lt;a href=&quot;http://work.co/grid/&quot;&gt;respsonsive grid&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Grid systems and zoomable UI: &lt;a href=&quot;http://jonikorpi.com/&quot;&gt;jonikorpi.com&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;For e.g. a zoomable ticket picker, could do it as canvas, divide it into tiles then redraw only the tiles you need.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;look-no-media-queries&quot;&gt;Look, no media queries!&lt;/h2&gt;
&lt;p&gt;(Vasilis van Gemert @vasilis)&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://vasilis.nl/presentaties/smashing/oxford/#/&quot;&gt;Slides&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode&quot;&gt;mixed-blend-mode&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;css columns for horizontal running text&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;if put an id on &lt;code class=&quot;highlighter-rouge&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;html&amp;gt;&lt;/span&gt;&lt;/code&gt; you can use a fragment id in the URI along with the &lt;code class=&quot;highlighter-rouge&quot;&gt;:target&lt;/code&gt; CSS selector to change the layout of the page. You can add another one onto &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;head&amp;gt;&lt;/code&gt;, and also onto &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;body&amp;gt;&lt;/code&gt;, and then you’ve got up to 3 layouts you can switch between via the URI.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Don’t use &lt;code class=&quot;highlighter-rouge&quot;&gt;vh&lt;/code&gt;/&lt;code class=&quot;highlighter-rouge&quot;&gt;vw&lt;/code&gt; units to style text, as that can get very crazy, but you can do this:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;font-size: calc(2em + 2vh + 2vw);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Even better though, is this:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;font-size: calc(4vw + 4vh + 4vmin);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;as this will give you perfectly scaled text inside any container and won’t break out.&lt;/p&gt;

&lt;p&gt;Can use viewport-relative units in flex-basis. , e.g. &lt;code class=&quot;highlighter-rouge&quot;&gt;vmax&lt;/code&gt;: can give you a differeing # coulumns, depending on the viewport width: the effects of a media query, without a media query.&lt;/p&gt;

&lt;h2 id=&quot;join-the-dots&quot;&gt;Join the dots&lt;/h2&gt;
&lt;p&gt;(Haydon Pickering @heydonworks)
Slides: http://slides.com/heydon/joining-up-the-dots#/&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;forcefeed.js(?)
Hegel’s dialectical synthesis: &lt;code class=&quot;highlighter-rouge&quot;&gt;git merge...&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;@t said: “If it’s not curlable, then it’s not the web”&lt;/p&gt;

&lt;p&gt;“How modules communicate is more importand than their properties” Alan Kay [also see Alla’s talk].&lt;/p&gt;

&lt;p&gt;HYPERLINKS FTW.&lt;/p&gt;

&lt;p&gt;Readability tools:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;hemmingwayapp.com&lt;/li&gt;
  &lt;li&gt;Alex (looks for gendered language)&lt;/li&gt;
  &lt;li&gt;Rousseau (picks up weasel words)&lt;/li&gt;
  &lt;li&gt;readability-checker&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;gov.uk aims for sentences no longer than 25 words.&lt;/p&gt;

&lt;p&gt;Haydon’s Logical Developer Falacies&lt;/p&gt;

&lt;p&gt;Communication is key! (see Aarron’s talk).&lt;/p&gt;

&lt;h2 id=&quot;addendum&quot;&gt;Addendum&lt;/h2&gt;
&lt;p&gt;Rachel Nabor’s links:
webanimationweekly.com
hacks.mozilla.org&lt;/p&gt;

&lt;hr /&gt;
&lt;p&gt;(&lt;a href=&quot;/2016/03/18/smashing-conference-2016-day-2/&quot;&gt;Find out what happened on day 2&lt;/a&gt;.)&lt;/p&gt;

</description>
        <pubDate>Fri, 18 Mar 2016 15:35:00 +0000</pubDate>
        <link>http://decodeuri.net/2016/03/18/smashing-conference-2016-day-1/</link>
        <guid isPermaLink="true">http://decodeuri.net/2016/03/18/smashing-conference-2016-day-1/</guid>
        
        
      </item>
    
      <item>
        <title>Smashingconf 2016: overview</title>
        <description>&lt;p&gt;The two related posts linked to below are the writeup of my raw notes from Smashingconf Oxford 2016. I’ll likely add to them as I come across errors, or can update with links to speakers slides or other resources. They contain my transcription of my hand-written notes I took while listening to the speakers. Their primary aim is to capture as much as possible while it’s fresh in my mind. There’s always a chance I’ve misunderstood something, or haven’t represented something quite right because I didn’t catch everything. If so, I apologise, I can only write so fast - and that’s faster than I type! Speaking of which, forgive the typos. I typed up the notes as fast as I could, so they’re a bit rough about the edges.&lt;/p&gt;

&lt;p&gt;A huge thank you to all of the speakers, and to Smashing for organising it, it was another phenomenally good conference.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/2016/03/18/smashing-conference-2016-day-1/&quot;&gt;Smashing Conf Day 1 (March 15th)&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Building great design teams (Aarron Walter)&lt;/li&gt;
  &lt;li&gt;Building a pattern language for the web (Alla Kholmatoma)&lt;/li&gt;
  &lt;li&gt;SVG in Motion (Sara Soueiden)&lt;/li&gt;
  &lt;li&gt;HTTP/2 (Patrick Hamann)&lt;/li&gt;
  &lt;li&gt;Understanding people (Chris Shiflett)&lt;/li&gt;
  &lt;li&gt;Dirty front end tricks (Vitaly Friedman)&lt;/li&gt;
  &lt;li&gt;Look, no media queries! (Vasilis van Gemert)&lt;/li&gt;
  &lt;li&gt;Join the dots (Haydon Pickering)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href=&quot;/2016/03/18/smashing-conference-2016-day-2/&quot;&gt;Smashing Conf Day 2 (March 16th)&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Design systems in difficult places (Mark Boulton)&lt;/li&gt;
  &lt;li&gt;Taking layout to the next level (Christopher Wright)&lt;/li&gt;
  &lt;li&gt;Designing the future of content (Hannah Donovon)&lt;/li&gt;
  &lt;li&gt;Devtools: an animated journey (Umar Hansa)&lt;/li&gt;
  &lt;li&gt;Overthinking design and embracing minutia (Jon Setzen)&lt;/li&gt;
  &lt;li&gt;Living design systems (Jina Bolton)&lt;/li&gt;
  &lt;li&gt;Modern workflow and tooling (Wes Bos)&lt;/li&gt;
  &lt;li&gt;Improving on screen legibilty (Tobias Frere-Jones)&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Fri, 18 Mar 2016 15:30:00 +0000</pubDate>
        <link>http://decodeuri.net/2016/03/18/smashing-conference-2016-overview/</link>
        <guid isPermaLink="true">http://decodeuri.net/2016/03/18/smashing-conference-2016-overview/</guid>
        
        
      </item>
    
      <item>
        <title>Useful resources for front end web development</title>
        <description>&lt;p&gt;I was talking to a friend who’s recently started learning front end development, and realised that the sheer abundance of posts on the topic makes it hard for a newcomer to know where which way to turn. In an attempt to provide some kind of orientation, I’ve quickly put together a short list of some of blogs and other resources I find useful myself. Hopefully others will benefit from this too, although obviously as this is a personal selection YMMV.&lt;/p&gt;

&lt;h2 id=&quot;general&quot;&gt;General&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://w3.org&quot;&gt;w3.org&lt;/a&gt; (the web standards body, incl. html5 spec. But not JavaScript.)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/&quot;&gt;developer.mozilla.org&lt;/a&gt; (good for nitty gritty technical details)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://caniuse.com/&quot;&gt;caniuse.com&lt;/a&gt; (check browser support for the feature you want to use)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.smashingmagazine.com/&quot;&gt;smashingmagazine.com&lt;/a&gt; and &lt;a href=&quot;http://alistapart.com/&quot;&gt;alistapart.com&lt;/a&gt; (two superb resources across the spectrum of front end development)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;html&quot;&gt;HTML&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://whatwg.org/&quot;&gt;whatwg.org&lt;/a&gt; (separate html5 spec - thankfully extremely similar to the w3c one)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://html5doctor.com/&quot;&gt;html5doctor.com&lt;/a&gt; (useful insight into html5 elements and their useage)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;css&quot;&gt;CSS&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://css-tricks.com/&quot;&gt;css-tricks.com&lt;/a&gt; (insightful articles &amp;amp; useful examples of many css techniques)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://csswizardry.com/&quot;&gt;csswizardry.com&lt;/a&gt; (thoughful posts on css organisation)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://davidcmoulton.github.io/css-selectors/&quot;&gt;davidcmoulton.github.io/css-selectors&lt;/a&gt; (I made this one, and refer to it quite often: it’s an example of every css selector I could think of [not updated with shadow DOM yet])&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;svg&quot;&gt;SVG&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://sarasoueidan.com/&quot;&gt;sarasoueidan.com&lt;/a&gt; (excellent, actionable, detailed posts on all matters svg)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It was tricky trying to distill JavaScript blogs suitable for a beginner, as so much seems to be aimed at intermediate level or higher. I’ll may update this post with js resources if I come across something suitable, but books might be the better bet if you’re starting to learn JavaScript with no prior programming experience.&lt;/p&gt;

&lt;p&gt;Finally, there’s &lt;a href=&quot;http://stackoverflow.com/&quot;&gt;stackoverflow.com&lt;/a&gt;, which describes itself as &lt;q&gt;a community of 4.7 million programmers, just like you, helping each other.&lt;/q&gt; It’s often a great place to find answers to questions you have. Just bear in mind that the quality of the answers can be uneven, so it can be a mixed blessing for a beginner.&lt;/p&gt;

&lt;p&gt;(Note this list isn’t trying to be definitive, and I doubt it’s very representative either bearing in mind the sheer volume of stuff out there, so apologies to anyone who’s offended I’ve not mentioned their contribution, Please don’t be, I’m sure you’re awesome! :-) )&lt;/p&gt;
</description>
        <pubDate>Wed, 09 Mar 2016 00:00:00 +0000</pubDate>
        <link>http://decodeuri.net/2016/03/09/useful-resources-for-front-end-web-development/</link>
        <guid isPermaLink="true">http://decodeuri.net/2016/03/09/useful-resources-for-front-end-web-development/</guid>
        
        
      </item>
    
      <item>
        <title>Smashingconf 2015: RWD performance optimisation</title>
        <description>&lt;p&gt;I was lucky enough to get to Smashingconf Oxford once again this year. In this post I cover the pre-conference workshop run by Guy Podjarny (&lt;a href=&quot;http://twitter.com/guypod&quot;&gt;@guypod&lt;/a&gt;), titled “Make a slow responsive website fast”. Guy is CTO for Akamai, a CDN company, and so unsurprisginly Akamai was mentioned a bit in the workshop, but never in an exclusive or selling manner, and always accompanied by mentioning free/open alternatives. It definitely wasn’t a sales pitch, and didn’t feel like one, which I appreciated.&lt;/p&gt;

&lt;p&gt;(A note on sources: this post is mainly from my notes and memories of the day. There are some statements that I don’t have sources for as I didn’t manage to record them as well as the statements themselves; I couldn’t type fast enough!)&lt;/p&gt;

&lt;h2 id=&quot;mobile-web-and-performance&quot;&gt;Mobile web and performance&lt;/h2&gt;

&lt;p&gt;Cute fact: there a 6-7 times more smartphones being activated every 45 minutes than there are babies being born.&lt;/p&gt;

&lt;p&gt;Plain fact: Akamai have seen mobile traffic on their network up from 9% in June 2012, to 36% 18 months later.&lt;/p&gt;

&lt;p&gt;We all know how desktop sites fail on mobile: through bad interactions, pages being too big, and pages being too complex.&lt;/p&gt;

&lt;p&gt;This performance impacts business results. Walmart measured download time vs conversion rate on its site, and as you might expect, the slower thee page load, the fewer conversions occurred.&lt;/p&gt;

&lt;p&gt;EBay performed a similar study that showed a 5% slowdown of the site cost 1% revenue; a 35% slowdown of the site cost them 5% revenue. They found a faster page caused a lower bounce rate and more pages viewed per session.&lt;/p&gt;

&lt;h2 id=&quot;history-lesson-dedicated-mobile-sites-mdot-sites&quot;&gt;History lesson: dedicated mobile sites (“mdot” sites)&lt;/h2&gt;

&lt;p&gt;In the days before responsive web design (RWD), businesses attempted to address the failure of desktop sites on mobile by creating dedicated mobile sites (often on an “m.” or “mobile.” subdomain, hence they’re known as “mdot” sites). These had the advantage at the time of being able to be built by a new team who didn’t need integrating into the main site team to ply their new-fangled mobile website trade, and were able to ship the mdot site without upsetting the main corporate dev site workflow. Of course after a while this duplication/separation was seen for the burden that it is: it usually requires duplication of content, of development and design.&lt;/p&gt;

&lt;p&gt;mdot sites are generally fast though.&lt;/p&gt;

&lt;p&gt;mdot sites tend to comprise smaller pages with fewer HTTP requests, so you get performance for free. But with an mdot site you typically have redirects, the latency within which can wipe out the gain of the smaller payload.&lt;/p&gt;

&lt;p&gt;These edge redirects (where you get sent to an mdot site, with the appropriate URL, if you’re on a device classified by the edge server as “mobile”), have problems of diluted SEO effect, device identification, and portabliity: sending someone a link to an mdot page can give them a horrid experience when they look at it on their large monitor.&lt;/p&gt;

&lt;p&gt;An alternative to edge redirects, which addresses the URL portabliity (and probably also the SEO) problems, is adaptive delivery. Here a single URL is used to serve either the desktop or the mdot site, again depending on whether the requesting device is described as “mobile”. So although an improvement, it still has the problem of device identification.&lt;/p&gt;

&lt;p&gt;Bearing in mind the sheer number of “mobile” devices out there today (Akamai have identified 8000 different devices on their network), and add to that the fact that with such a plethora of screen sizes and resolutions the “mobile” spectrum is more of a continuum than a binary situation these days, then the suitability of an mdot site in today’s web landscape is generally low.&lt;/p&gt;

&lt;!-- [Aside: Google's design guidelines recommend using a phone as a guide when designing for TV. Although the screen sizes are extremely different, you look at the TV screen from much further away.]

According to the HTTP archive, mdot sites are in a minority, at only 26%, which balance are either desktop sites or responsive sites. --&gt;

&lt;h2 id=&quot;present-lesson-responsive-web-design&quot;&gt;Present lesson: Responsive Web Design&lt;/h2&gt;

&lt;p&gt;Google recommend RWD for SEO. If nothing else, this is driving adoption. In October 2014, of the top 100000 websites, 18% used responsive design, up from 10% only 11 months previously.&lt;/p&gt;

&lt;p&gt;Almost no difference in number HTTP requests between RWD site at desktop width, and the same site at narrow width with a mobile user agent.&lt;/p&gt;

&lt;p&gt;Average compute time is almost double for an RWD site compared to an mdot site (~6s and ~3s respectively).&lt;/p&gt;

&lt;p&gt;HTTP archive trends show that although the number of images is staying roughly the same, the average size of an image has increased significantly (a JPEG file’s size on an RWD site is often 150% larger than on a traditional desktop-only site). RWD isn’t causing more objects, it’s causing objects to be bigger. And for objects, read images.&lt;/p&gt;

&lt;p&gt;There are great reasons &lt;a href=&quot;http://timkadlec.com/2013/06/why-we-need-responsive-images/&quot;&gt;why we need responsive images&lt;/a&gt; which I won’t go over again here. Oh okay, just one then (and this one’s less commonly mentioned that some others): when the image scaling is handled on the client, the this generally happens on the GPU. The whole image is pushed from the CPU onto the GPU through what’s a pretty narrow pipe, before the image can be scaled. This is costly.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;http://respimages.org&quot;&gt;Responsive Images Community Group&lt;/a&gt; has championed the issue of responsive images, and thanks to their efforts we have the following available either as native implementations, or polyfilled:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;srcset&lt;/code&gt; attribute&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;sizes&lt;/code&gt; attribute&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; element&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As the first to have agreement among (some) browser vendors to implement, srcset has pretty good native support now. Sizes and picture came later and so currently need polyfilling. So far, my goto polyfill for responsive images has been  &lt;a href=&quot;https://github.com/scottjehl/picturefill&quot;&gt;picturefill&lt;/a&gt;, maintained by Scott Jehl. In the workshop, Guy mentioned another called &lt;a href=&quot;https://github.com/aFarkas/respimage&quot;&gt;respimage&lt;/a&gt; maintained by Alexander Farkas, which looks interesting, but I’ve not used (yet).&lt;/p&gt;

&lt;p&gt;Eric Portis has a couple of great posts on how to use these new responsive image tools: &lt;a href=&quot;http://alistapart.com/article/responsive-images-in-practice&quot;&gt;Responsive images in practice&lt;/a&gt; and the older &lt;a href=&quot;http://ericportis.com/posts/2014/srcset-sizes/&quot;&gt;srcset and sizes&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;exercises&quot;&gt;Exercises&lt;/h2&gt;

&lt;p&gt;The exercises were set up on individual Magento servers, so we could individually break things without inconveniencing anyone else. One page in particular was used as the target of most of the optimisations, this is referred to below as the ‘test page’.&lt;/p&gt;

&lt;p&gt;(Note: if I talk about relative merits of an approach requiring JavaScript or not, I’m referring to the native implementation. Obviously if the behaviour is polyfilled, that will be JavaScript dependent until support is such that the polyfill can be removed.)&lt;/p&gt;

&lt;h2 id=&quot;webpagetest&quot;&gt;WebPageTest&lt;/h2&gt;

&lt;p&gt;We were introduced to &lt;a href=&quot;http://www.webpagetest.org/&quot;&gt;WebPageTest&lt;/a&gt;, a tool for running speed tests from multiple geographical locations, using real browsers at real connection speeds. It’s a free service, and you can use it manually online, &lt;a href=&quot;http://calendar.perfplanet.com/2014/free-webpagetest-api-keys/&quot;&gt;request a key&lt;/a&gt; to give you 200 automatable page loads, or install it yourself on a server for full integration into your CI stack.&lt;/p&gt;

&lt;p&gt;When making optimisations to a site, it’s important you have a baseline to check the effect of what you’re changing. We set off a couple of WebPageTest runs to baseline the page on both desktop and mobile before making any changes.&lt;/p&gt;

&lt;p&gt;After each optimisation, we ran WebPageTest to see what its effect.&lt;/p&gt;

&lt;p&gt;Obviously for site features it’s not okay if something core only works for 90% of users. With optimisations though, it is okay if they only work for 90% of users.&lt;/p&gt;

&lt;h2 id=&quot;exercise-1-download-and-shrink&quot;&gt;Exercise 1: download and shrink&lt;/h2&gt;

&lt;h3 id=&quot;use-case&quot;&gt;Use case&lt;/h3&gt;

&lt;p&gt;Huge images are being sent to the client for the client to shrink to fit as necessary.&lt;/p&gt;

&lt;h3 id=&quot;optimisation&quot;&gt;Optimisation&lt;/h3&gt;

&lt;p&gt;Only send image of appropriate size to client.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Modified the server-side code to provide unique urls for the individual images of different (appropriate) sizes.&lt;/li&gt;
  &lt;li&gt;Added &lt;code class=&quot;highlighter-rouge&quot;&gt;srcset&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;sizes&lt;/code&gt; attributes to the image elements:&lt;/li&gt;
&lt;/ul&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;img&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;[default/fallback image path]&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;srcset=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;[small image path] 300w, [medium image path] 345w
          [large image path] 500w&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;sizes=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;(max-width: 640px) 300px, (max-width: 800px) 345px,
         (max-width: 1200px) 500px&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;alt=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;[something appropriate]&quot;&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Although we only specified width in this case, srcset is often used to specify resolution. Images included in a srcset attribute value are considered equivalent. Because of this, srcset only provides hints to the browser for resolution switching, the browser is not obliged to respect it.&lt;/p&gt;

&lt;h2 id=&quot;exercise-2-download-and-hide&quot;&gt;Exercise 2: download and hide&lt;/h2&gt;

&lt;h3 id=&quot;use-case-1&quot;&gt;Use case&lt;/h3&gt;

&lt;p&gt;Images are being sent to the client regardless of the client environment, and are just not shown if e.g. the viewport is too narrow.&lt;/p&gt;

&lt;h3 id=&quot;optimisation-1&quot;&gt;Optimisation&lt;/h3&gt;

&lt;h4 id=&quot;option-1-use-javascript&quot;&gt;Option 1: use JavaScript&lt;/h4&gt;

&lt;p&gt;Like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
 &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;loadReal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;img&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;img&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;img&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;offsetParent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;nx&quot;&gt;img&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;onload&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;nx&quot;&gt;img&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;src&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;img&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getAttribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;data-src&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
 &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
...
&lt;span class=&quot;nt&quot;&gt;&amp;lt;img&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;1x1.jpg&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;onload=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;loadReal(this);&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;data-src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;[url to desired image]&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;alt=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;[alt of desired image]&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;JavaScript is required to show these images though.&lt;/p&gt;

&lt;h4 id=&quot;option-2-use-picture&quot;&gt;Option 2: use &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;picture&amp;gt;&lt;/code&gt;:&lt;/h4&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;picture&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;source&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;media=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;(min-width: 800px)&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;[url to desired image]&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;img&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;1x1.jpg&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/picture&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Unlike images specified in &lt;code class=&quot;highlighter-rouge&quot;&gt;srcset&lt;/code&gt;, the child &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;source&amp;gt;&lt;/code&gt; elements of &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; are not considered equivalent. This means that whatever media query you specify there the browser is required to respect. This can make things slower though, so only use &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; if you need the &lt;a href=&quot;http://usecases.responsiveimages.org/&quot;&gt;art direction usecase&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Note that afaik the &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; element doesn’t allow for a ‘no-image’ option, hence the 1x1 still specified within &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;picture&amp;gt;&lt;/code&gt;’s &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;img&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Of the two aproaches above, favour &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; as it’s a (albiet poiyfilled) native implementation. Always favour standards-based native implementation over custom rolled.&lt;/p&gt;

&lt;h2 id=&quot;exercise-3-overdownloading-css&quot;&gt;Exercise 3: overdownloading css&lt;/h2&gt;
&lt;p&gt;Byte for byte CSS has a massive impact on web page performance, because it can be blocking.&lt;/p&gt;

&lt;h3 id=&quot;use-case-2&quot;&gt;Use case&lt;/h3&gt;
&lt;p&gt;Main CSS files contain significantly over 10% of CSS within media queries that will never apply to the current page.&lt;/p&gt;

&lt;h3 id=&quot;optimisation-2&quot;&gt;Optimisation&lt;/h3&gt;
&lt;p&gt;Refactor the media-query-specific CSS into file(s) specific for the media query/queries. Then conditionally load them.&lt;/p&gt;

&lt;h4 id=&quot;option-1-use-link-media&quot;&gt;Option 1: use &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;link media...&lt;/code&gt;:&lt;/h4&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;link&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rel=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;stylesheet&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text/css&quot;&lt;/span&gt;  &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;base.css&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;media=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;all&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;link&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rel=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;stylesheet&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text/css&quot;&lt;/span&gt;  &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;mobile.css&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;media=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;(max-width:799px)&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;link&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rel=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;stylesheet&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text/css&quot;&lt;/span&gt;  &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;desktop.css&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;media=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;(min-width:800px)&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h4 id=&quot;option-2-use-javascript&quot;&gt;Option 2: use JavaScript:&lt;/h4&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;  &lt;span class=&quot;nt&quot;&gt;&amp;lt;link&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rel=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;stylesheet&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text/css&quot;&lt;/span&gt;  &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;base.css&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;media=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;all&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;link&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rel=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;stylesheet&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text/css&quot;&lt;/span&gt;  &lt;span class=&quot;na&quot;&gt;data-src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;mobile.css&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;data-mq=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;(max-width:799px)&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;link&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rel=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;stylesheet&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text/css&quot;&lt;/span&gt;  &lt;span class=&quot;na&quot;&gt;data-src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;desktop.css&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;data-mq=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;(min-width:800px)&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;scripts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getElementsByTagName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;link&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;scripts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;// Test if the Media Query matches&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;mq&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;scripts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getAttribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;data-mq&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;matchMedia&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;matches&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// If so, append the new (async) element.&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;link&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;rel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'stylesheet'&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'text/css'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;href&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;scripts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getAttribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;data-src&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Using &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;link&amp;gt;&lt;/code&gt;, the file that is under a non-matching media query is still loaded, but its load is deferred so it doesn’t block. This was unexpected, but is apparently standard browser behaviour. I guess so that if the device switches orientation, the CSS for it is already in memory and wouldn’t have to be fetched, which could have really horrible effects.&lt;/p&gt;

&lt;p&gt;The JavaScript approach gives you complete control over the load, and beacause we didn’t ask for it, it didn’t defer-load the non-matching media query CSS.&lt;/p&gt;

&lt;p&gt;As for the previous exercise, prefer the &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;link&amp;gt;&lt;/code&gt; element approach over the JavaScript approach: it’s a native implementation, and so is a better choice.&lt;/p&gt;

&lt;p&gt;This conditional loading introduces extra requests, which is the tradeoff. Whether it’s worth doing for your particular CSS is a value judgement you have to make in your own circumstances.&lt;/p&gt;

&lt;h3 id=&quot;exercise-4-ress-responsive--server-side&quot;&gt;Exercise 4: RESS (Responsive + Server Side)&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;http://www.smashingmagazine.com/2013/10/08/responsive-website-design-with-ress/&quot;&gt;RESS&lt;/a&gt; is an approach that pushes onto the server the conditional assembly of a design response, where it makes sense to. &lt;em&gt;RESS does not replace responsive design on the client&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Possible approaches are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;regex the user agent string&lt;/li&gt;
  &lt;li&gt;device characteristics&lt;/li&gt;
  &lt;li&gt;client hints (not ready yet)&lt;/li&gt;
  &lt;li&gt;cookies&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;using-cookies&quot;&gt;Using cookies&lt;/h4&gt;

&lt;p&gt;Can have a JavaScript function that sets a cookie recording the viewport width. The server tests for this and only sends down content for wide screen if it’ll fit.&lt;/p&gt;

&lt;p&gt;For example, in JavaScript:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;writeCookie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;today&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;the_date&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;December 31, 2023&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;the_cookie_date&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;the_date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toGMTString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;the_cookie&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;users_width=&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;innerWidth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;the_cookie&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;the_cookie&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;;expires=&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;the_cookie_date&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;; path=/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cookie&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;the_cookie&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;writeCookie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;then on the server, e.g. in PHP:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-php&quot; data-lang=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;isset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$_COOKIE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;users_width&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])){&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$_COOKIE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;users_width&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;650&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;The_Content_Only_For_Wide_Viewports&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;ul&gt;
  &lt;li&gt;dependency on js for wide view content&lt;/li&gt;
  &lt;li&gt;will only take effect on page load, not window resize nor device orientation switch (unless use ajax to set cookie again with new width, and dynamically inject the content as needed?).&lt;/li&gt;
  &lt;li&gt;doesn’t work for initial page load as cookie needs to be set first.&lt;/li&gt;
  &lt;li&gt;can break caching&lt;/li&gt;
  &lt;li&gt;how much do you gain with this technique? It may not be worth it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Consider not including the content at all if it wouldn’t show up in landscape nor portrait&lt;/p&gt;

&lt;h4 id=&quot;using-edge-side-includes-esis&quot;&gt;Using edge side includes (ESIs)&lt;/h4&gt;

&lt;p&gt;ESIs are like server side includes, but are in the cache. They were originally developed in 2001 to set cache expiry on fragemnts of a page, rather than the page itself.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;available in Varnish, Apache Traffic Server, Akamai…&lt;/li&gt;
  &lt;li&gt;open standard, but some implementations have written extensions&lt;/li&gt;
  &lt;li&gt;enables you to cache a single page, but have it with whatever variations you want.&lt;/li&gt;
  &lt;li&gt;If relying on ESIs, application won’t work without them, unless you configure application with e.g. a flag to indicate when ESIs not in use, that causes server to run code to generate content etc that would otherwise be taken into account by the ESIs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/tomav/Varnish-ESI-Example&quot;&gt;Example in Varnish&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;exercise-image-transcoding&quot;&gt;Exercise Image transcoding&lt;/h3&gt;

&lt;p&gt;Image management vital for any website. Can have many, many image variants for each actual image.&lt;/p&gt;

&lt;p&gt;There are (relatively) new image formats like WebP, JPEG2000 etc that have better compression than JPEG and PNG, but there is no solid cross browser support for any of these at the moment.&lt;/p&gt;

&lt;p&gt;If you can separate image transcoding from the application, then you can have image selection on a per browser basis. You can be agile about what image gets served to what browser/device, as the situation evolves and new formats come along, or support for current formats improve.&lt;/p&gt;

&lt;p&gt;Essentially you have image generation and image routing as two independent functions. Image routing is not new, &lt;a href=&quot;http://www.imagemagick.org/&quot;&gt;ImageMagik&lt;/a&gt; is good for this. Also consider giving Tinysource(?) and image converter(?)&lt;/p&gt;

&lt;p&gt;You could adjust the image quality to the network conditions, but assessing the network is hard. Akamai use round trip time to describe the network as Excellent, Average or Poor.&lt;/p&gt;

&lt;p&gt;Serving the right image is difficult, need to consider:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;browser version&lt;/li&gt;
  &lt;li&gt;network&lt;/li&gt;
  &lt;li&gt;screen resolution/dimensions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pick a tool wisely. Take into account:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;ease of workflow&lt;/li&gt;
  &lt;li&gt;first view of performance&lt;/li&gt;
  &lt;li&gt;scaleability&lt;/li&gt;
  &lt;li&gt;code complexity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If choosing whether to send down a JPEG or a WebP file to the client, you could use a different URL for each format, and write the URLs in the HTML accordingly. The problem with this approach is that if a link is shared and attempted to be opened in a non-supporting client, the view will fail. Also Google will see these as two different URLs and your SEO will be diluted.&lt;/p&gt;

&lt;p&gt;Instead, the recommended approach is to have a single URL that supplied different images using RESS. This may not be easy.&lt;/p&gt;

&lt;p&gt;There’s a good read by &lt;a href=&quot;https://twitter.com/igrigorik&quot;&gt;Ilya Grigorik&lt;/a&gt; on &lt;a href=&quot;https://www.igvita.com/2013/05/01/deploying-webp-via-accept-content-negotiation/&quot;&gt;Deploying WebP via accept content negotiation&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;and-finally&quot;&gt;And finally&lt;/h2&gt;

&lt;p&gt;Thanks to Guy (and to his facilitators Michael and Ellen), and Smashingconf for a great workshop! Really interesting, I learned a lot.&lt;/p&gt;

&lt;!--
## Misc notes

- WebPageTest enables Single Point of Faliure tests, e.g. what happens if connect.facebook.net is unavailable. (Solution: async them if you can)
- browser loading indicator stops when onload fires.
- how akamai edge servers see your client: http://edc.edgesuite.net/

### Things to follow up

- HTTP archive: trends
- WebPageTest (Motorola G has most agents on WebPageTest)
- paul kinlans css bookmarklet
- https://paul.kinlan.me/detecting-critical-above-the-fold-css/
- spof-o-matic chrome extension: see what happens to your page when scripts are made unavailable
- bit.ly/rf-free

--&gt;
</description>
        <pubDate>Mon, 16 Mar 2015 00:00:00 +0000</pubDate>
        <link>http://decodeuri.net/2015/03/16/smashingconf-2015-rwd-performance-optimisation/</link>
        <guid isPermaLink="true">http://decodeuri.net/2015/03/16/smashingconf-2015-rwd-performance-optimisation/</guid>
        
        
      </item>
    
      <item>
        <title>Meetup writeup: The Science of (Bio) Data Visualisation</title>
        <description>&lt;p&gt;Yesterday evening I went along to the &lt;a href=&quot;http://www.meetup.com/Cambridge-Visualization-of-Biological-Information-Meetup/events/219018174/&quot;&gt;Science of (Bio) Data Visualisation&lt;/a&gt; meetup in Cambridge. There were 2 talks: one by Catagay Turkay, who is researching data visualisation, and one from a design company, &lt;a href=&quot;http://science-practice.com/&quot;&gt;Science-Practice&lt;/a&gt;, who specialise in the science sector. The two talks complemented each other well.&lt;/p&gt;

&lt;h2 id=&quot;designing-interactive-visualisations-to-solve-analytical-problems&quot;&gt;Designing interactive visualisations to solve analytical problems&lt;/h2&gt;

&lt;p&gt;Catagay Turkay is researching applied data science in the giCentre of City University, London. He’s interested in perceptually optimised visualisations, and in using computational tools in interactive visual analysis. Biological visualisations specifically interest him because they tend to be based on large, heterogeneous datasets, often at multiple scales, and because they often describe dynamic processes, they include temporal complexity, which makes them more challenging.&lt;/p&gt;

&lt;h3 id=&quot;visualisation-can-help&quot;&gt;Visualisation can help:&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;ease of cognition&lt;/li&gt;
  &lt;li&gt;relate multiple aspects&lt;/li&gt;
  &lt;li&gt;compare multiple computational outputs&lt;/li&gt;
  &lt;li&gt;investigate uncertainties&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They enable and foster &lt;strong&gt;hypothesis generation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Catagay sees visualisation as operating on three levels: as a presentation medium; with interaction, and with integrated computation.&lt;/p&gt;

&lt;h3 id=&quot;visualisations-as-presentation-medium&quot;&gt;Visualisations as presentation medium&lt;/h3&gt;

&lt;p&gt;He showed an example of striking imagery with an illustration of an &lt;em&gt;E. coli&lt;/em&gt; cell, highly coloured, with organelles clearly visible. It’s both correct, and aesthetic.&lt;/p&gt;

&lt;p&gt;Nature Methods publishes a regular Points of view column on how to make better visualisations. You can see &lt;a href=&quot;http://blogs.nature.com/methagora/2013/07/data-visualization-points-of-view.html&quot;&gt;this list of them&lt;/a&gt;, but the actual articles are paywalled.&lt;/p&gt;

&lt;h3 id=&quot;visualisations-with-interaction&quot;&gt;Visualisations with interaction&lt;/h3&gt;

&lt;p&gt;Example of &lt;a href=&quot;http://www.cs.utah.edu/~miriah/mizbee/Overview.html&quot;&gt;Mizbee&lt;/a&gt;, a free Synteny browser (also, see the article’s record on &lt;a href=&quot;http://www.ncbi.nlm.nih.gov/pubmed/19834152&quot;&gt;PubMed&lt;/a&gt;, although the actual IEEE paper is behind a paywall).&lt;/p&gt;

&lt;p&gt;Strengths of this include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;the ability to compare the overlap between 2 genes&lt;/li&gt;
  &lt;li&gt;can link multiple aspects&lt;/li&gt;
  &lt;li&gt;interactively vary the focus&lt;/li&gt;
  &lt;li&gt;display multiple scales concurrently (multiple scales seem to be a situation reasonably specific to biology).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;visualisations-with-integrated-computation&quot;&gt;Visualisations with integrated computation&lt;/h3&gt;

&lt;p&gt;Rather than provide an interface to interact with static aspects  of the dataset (albeit in creative ways), here computation on the data is employed during the data visualisation process itself. For example by making a cluster algorithm part of the actual visualisation process.&lt;/p&gt;

&lt;p&gt;The strength of this approach is the combination of human perceptual abilities with a computer’s processing power. AKA &lt;strong&gt;Visual Analytics&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Example given was &lt;a href=&quot;http://caleydo.github.io/projects/stratomex/&quot;&gt;Stratomex&lt;/a&gt; by Caleydo. It’s described as an “Integrative visualization of stratified heterogeneous data for disease subtype analysis”. It’s been used for cancer subtype analysis, and he showed multiple stratifications with many patients, and some sample overlaps: which means you can compare the results of different algorithms.&lt;/p&gt;

&lt;p&gt;What’s powerful here is that you can link gene expression data with chemical pathway data and clinical data. Visualisations are good here, because:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;with multiple, linked datasets you can improve your interpretation&lt;/li&gt;
  &lt;li&gt;multiple computational results  can help you deal with uncertainty&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This allows for a fast iterative process that means you can prototype many ideas quickly. You won’t get all the answers from this high level treatment, but it can help you narrow down ideas of interest that is worth putting under more rigorous analysis.&lt;/p&gt;

&lt;h3 id=&quot;outlook&quot;&gt;Outlook&lt;/h3&gt;

&lt;p&gt;Interaction and exploratory analysis is key.&lt;/p&gt;

&lt;p&gt;We need seamless support from integrated computations (e.g. t-tests).&lt;/p&gt;

&lt;h3 id=&quot;qa&quot;&gt;Q&amp;amp;A&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;What work is going on to investigate new methods of interaction, to complement all this work on new methods of visualisation?&lt;/em&gt;&lt;/p&gt;

    &lt;p&gt;There is a lot of work going on in the HCI field to do with this, not crossed over into the visualisation world yet.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;What libraries are people using for their visualisations?&lt;/em&gt;&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;http://d3js.org/&quot;&gt;d3&lt;/a&gt; (JavaScript)&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;http://trifacta.github.io/vega/&quot;&gt;vega&lt;/a&gt; (JavaScript)&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;http://www.statmethods.net/advgraphs/interactive.html&quot;&gt;GGobi plugin for R&lt;/a&gt; (R)&lt;/li&gt;
      &lt;li&gt;Catagay does a lot of his work using Python&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;closing-remarks&quot;&gt;Closing remarks&lt;/h3&gt;

&lt;p&gt;Good design principles are essential
for maximising the perceptual capabilities of the analyst. This is integral to good visualisations.&lt;/p&gt;

&lt;p&gt;Scientists should collaborate with designers/visualisation experts to produce better visualisation outputs.&lt;/p&gt;

&lt;h2 id=&quot;sequence-bundles&quot;&gt;Sequence bundles&lt;/h2&gt;

&lt;p&gt;This talk was given by the design agency Science-Practice that specialise in science-related projects in many disciplines. The sequence bundles came out of the effort to work out a new way of visualising protein chains in antibiotic resistance genes in MSA. Something to do with an entry for the &lt;a href=&quot;https://longitudeprize.org/challenge/antibiotics&quot;&gt;Longitude Prize 2014 antibiotics challenge&lt;/a&gt;. Their pitch was “Designing visualisations to enable discovery of data features that would otherwise remain hidden.”&lt;/p&gt;

&lt;h3 id=&quot;design-process&quot;&gt;Design process&lt;/h3&gt;

&lt;p&gt;They talked through their design process: it was their process that helped them discover hidden information in the sequence datasets.&lt;/p&gt;

&lt;p&gt;The first step was to learn about bioinformatics. Science-Practice are only a handful of people, but they have a scientist on staff in order to help the transfer of scientific knowledge into the design team. Necessary as they have projects in different scientific areas.&lt;/p&gt;

&lt;p&gt;They played with various ideas of representing a protein sequence, but decided to focus on the sequence characteristic of it representing a chain of contiguous amino acids.&lt;/p&gt;

&lt;p&gt;Having decided on a chain representation, their chosen way of comparing 1809 protein sequences was by graphing as a ribbon connecting the amino acids on the y-axis, and the sequence position on the x-axis. Partial transparency was very important here, in order to see patterns of overlap.&lt;/p&gt;

&lt;p&gt;They then played about with many design elements, e.g. colour, spacing of the y-axis, filtering out different info… they changed the layout a few times, he showed one where they tried a string visualisation.&lt;/p&gt;

&lt;p&gt;Their playing revealed some surprises that as far as they knew were not known to the data authors, for example a highly conserved residue at position 13. They also found some things that were not as obvious as expected, and there was some considerable variations from the consensus sequence. This was only discoverable because they decided to visualise each individual sequence in full, amino acid by connected amino acid. If they’d performed any kind of transformation on the sequence data before visualising it, these nuances would very likely have been missed.&lt;/p&gt;

&lt;p&gt;Interesting that these discoveries came to light during the design process.&lt;/p&gt;

&lt;p&gt;On the back of this they’ve developed a desktop tool, and a lighter weight web tool, to enable you to use the sequence bundle approach to visualise not only protein sequences, but also DNA and RNA sequences. The aim is to help scientists uncover information hidden within sequences without having to go through the design process themselves. They had a group of 70 users in a study that they interviewed and got feedback from during the development of the tool [not much info on the user research process, unfortunately].&lt;/p&gt;

&lt;p&gt;You can &lt;a href=&quot;http://science-practice.com/projects/sequence-bundles/&quot;&gt;read more about sequence bundles on their website&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; Science-Practice have pointed out that there is a report published as part of the Proceedings of the 3rd Annual Symposium on Biological Data Visualization: Data Analysis and Redesign Contests. It’s available at BioMedCentral: &lt;a href=&quot;http://www.biomedcentral.com/1753-6561/8/S2/S8&quot;&gt;Sequence Bundles: a novel method for visualising, discovering and exploring sequence motifs&lt;/a&gt; (open access).&lt;/p&gt;

&lt;h2 id=&quot;closing&quot;&gt;Closing&lt;/h2&gt;
&lt;p&gt;This was a great meetup. Thanks to the two speakers, and to William Spooner for organising. It was good to reconnect with old friends, and make some new ones. I hope I’ll be able to make the next one.&lt;/p&gt;

&lt;p&gt;(P.S. This writeup is based on my hastily scribbled notes. I think it’s pretty accurate, but if you were speaking that night, and I’ve horribly misrepresented what you said, please get in touch so I can make things right.)&lt;/p&gt;
</description>
        <pubDate>Fri, 16 Jan 2015 19:45:08 +0000</pubDate>
        <link>http://decodeuri.net/2015/01/16/meetup-writeup-science-of-data-visualistion/</link>
        <guid isPermaLink="true">http://decodeuri.net/2015/01/16/meetup-writeup-science-of-data-visualistion/</guid>
        
        
      </item>
    
  </channel>
</rss>
