<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Florian Schulz on Medium]]></title>
        <description><![CDATA[Stories by Florian Schulz on Medium]]></description>
        <link>https://medium.com/@getflourish?source=rss-303939833494------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*CXMusntSa1t1eARP2cohFQ.jpeg</url>
            <title>Stories by Florian Schulz on Medium</title>
            <link>https://medium.com/@getflourish?source=rss-303939833494------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 14 Nov 2026 13:01:28 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@getflourish/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Why don’t we use HTML to author web components?]]></title>
            <link>https://medium.com/@getflourish/why-dont-we-use-html-to-author-web-components-10440432390e?source=rss-303939833494------2</link>
            <guid isPermaLink="false">https://medium.com/p/10440432390e</guid>
            <category><![CDATA[html]]></category>
            <category><![CDATA[css]]></category>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[Florian Schulz]]></dc:creator>
            <pubDate>Tue, 26 Oct 2021 15:27:09 GMT</pubDate>
            <atom:updated>2021-10-27T08:07:28.378Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*NKwqWGnQf15ZiqWYNVGmjQ.png" /></figure><p>In this article I will explain how we <em>could</em> use HTML to author web components instead of using JavaScript only.</p><p>This article is not about frontend frameworks that all offer one or the other way to work with components. Frameworks are great, but now it’s 2021, and we are now able to create web components as <em>custom elements</em>.</p><p>But when I saw examples where HTML templates were defined as plain <em>strings</em>,<em> template literals</em> or even with <em>document.createElement()</em>, I stopped. Why all this special treatment, just to enable encapsulation?</p><p>Yes, there are countless libraries that promise to make it easier, but they all require their own syntax with decorators or special conventions. They promise to make things easier, but instead burden us with even more things to learn.</p><p>There must be something… simpler?</p><h3>Introducing: “HTML Components”</h3><p>It took me a while until I formed a new understanding of HTML. Previously for me, <strong>HTML was synonymous with websites.</strong></p><p>Until recently, I never thought of <strong>HTML files as components</strong>. But I think they can be. HTML provides all the parts that we need to author self-contained components that just work on their own. The idea of <a href="https://www.w3.org/TR/NOTE-HTMLComponents">HTML Components</a> isn’t new. In fact, it has been described already in <a href="https://www.w3.org/TR/NOTE-HTMLComponents">1998</a>.</p><p>But back to today, with my proof-of-concept, we can import custom elements in two new ways:</p><h4>Option 1: &lt;custom-element&gt;</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*V9M8hYxkBo1H8zNd7Bw4Ww.png" /></figure><p>This is a special custom element called, well, &lt;custom-element&gt; that will import the component. The imported component will then replace the &lt;custom-element&gt;. This syntax is inspired by elements such as &lt;iframe&gt;, &lt;img&gt;, &lt;object&gt;, &lt;embed&gt;, etc. that use a “src” attribute to embed external content.</p><p>After importing the component, you can then also use the component like that: &lt;color-picker&gt;.</p><h4>Option 2: HTML Import Syntax</h4><p>Alternatively, we can use the deprecated HTML Imports syntax by adding a link to the head of our document where we want to import the custom element:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*98c2_b_smjCO0KST75eoKQ.png" /></figure><p>With both options, we can use a “name” attribute to set or change the name of the imported component. This can be useful if we’re importing multiple &lt;color-picker&gt; elements. Since HTML components are not responsible for registering themselves, we have control over it.</p><p>&lt;link rel=&quot;module&quot; href=&quot;<a href="https://my.domain.tld/fancy-color-picker.html">fancy-color-picker.html</a>&quot; name=&quot;color-picker&quot;&gt;</p><p>Before I go into more detail, here’s an example:</p><ul><li>Here’s a <a href="https://codepen.io/getflourish/pen/ea4587d6dbd24cb4b03bb954a0e6e079">color-picker.html</a> hosted on Codepen.</li><li>Another <a href="https://codepen.io/getflourish/pen/a721fbd12caf190153451b3a7ff3acef">Codepen</a> that imports the &lt;color-picker&gt;</li></ul><p>Since we’re importing .html, not .js, we’ll be able to re-use the structure that HTML provides us, not for a website, but a component:</p><p><strong>&lt;head&gt; with &lt;meta&gt; tags</strong></p><p>Here, we can define meta data for our component, such as a title or other things that we might be tempted to stuff in a <em>package.json</em>.</p><p><strong>&lt;link&gt;</strong></p><p>Here, we can import external assets, such as fonts from a CDN or shared styles. Although I believe that components can only be sustainable without hosted external dependencies, linking other First Party resources is useful. Since we’re authoring standard HTML, the browser will take care of loading these resources.</p><p><strong>&lt;body&gt;</strong></p><p>Here, we can write standard, semantic HTML. The &lt;body&gt; serves as the “root” of our component. We can define &lt;slot&gt; elements, too!</p><p><strong>&lt;style&gt;</strong></p><p>Here, we can write standard CSS and use standard selectors, even body {} and h1 {}, without thinking about naming and scoping. Imagine it like that: if you open your HTML-Component in your browser, it will behave like a normal website. You only need to think about your component styles, but not the whole world in which the component might be placed later. The ShadowDOM will take care of it.</p><p><strong>&lt;script&gt;</strong></p><p>Here, we can write standard JavaScript. We can use DOM-APIs such as document.querySelector and element.addEventListener. No class methods, no getter/setters, … We can even load JavaScript libraries here. Don’t feel like syncing data between state and DOM? Try <a href="https://github.com/vuejs/petite-vue">petite-vue</a>, <a href="https://alpinejs.dev/">Alpine.js</a> or your favorite reactive state management library.</p><h4>Wait fool… you’re just describing HTML here!?</h4><p>That’s right. For me, HTML is sort of a component format. So far we’ve used it to define everything that is required for a website to work. But because components are just smaller versions of that, HTML may be a capable format for authoring web components. You don’t need to learn how to write a constructor for a CustomElement and then figure out a way to write your multi-line template as a string or using createElement() all over the place. All you need is your knowledge about HTML as a document format.</p><p>Instead of moving all our web components into JavaScript and with it loose a lot of simplicity, let’s see how far we can take HTML instead.</p><h4>This sounds too good to be true…</h4><p>Right. If this was possible through a native browser API, I’d be done here. I’d link to further documentation on MDN and call it a day.</p><p>Unfortunately, native HTML imports were forgotten in favour of ES6 Module Imports.</p><p>Here’s what user <a href="https://webmasters.stackexchange.com/questions/127482/on-what-specific-grounds-were-html-imports-rejected-deprecated-and-removed"><em>Rounin</em></a> says on StackOverflow:</p><blockquote>It wasn’t so much that the concept behind HTML Imports was no good. It was simply that the implementation architecture — initially developed in 2011, a long time before ES6 Modules were finalised — has proven far from optimal, especially given the evolution, more recently, of more sophisticated technologies.</blockquote><p>So while HTML <em>Imports</em> are dead, <a href="https://github.com/WICG/webcomponents/blob/gh-pages/proposals/html-modules-explainer.md">HTML <em>Modules</em></a> seem to be an active proposal.</p><p>But after briefly looking at it, it looks as if authoring HTML modules requires special treatment:</p><p>The template has to go, well, in a &lt;template&gt; tag. That makes the whole thing not work standalone in a browser. The HTML module also has to define exports to then be imported using ES6 module syntax.</p><p>To summarize: everything is bended towards JavaScript. And while yes, most web components will be interactive and require JavaScript, let’s not throw all the simplicity and capability that comes with HTML documents over board.</p><h4>So, how do your boring “HTML Components” work?</h4><p>It’s simple: we author components in HTML files. Write markup, styles, scripts. We develop and test it in isolation. Now the interesting part is to make the component work in a different environment where it is imported into another component, website or app.</p><p>To make components play together, we need a way to control the components from the outside context and a way for our component to communicate with its outside context.</p><h4>Attributes, Props, …</h4><p>Usually, we would need to define a static getter <em>observedAttributes</em> where we define the attributes of a custom element. Since we’re not writing a class at all, we need a different way. <strong>There are different options:</strong></p><ol><li><strong>Meta Tags:</strong> We <em>could</em> use meta tags in the head of our HTML component and define attributes there.</li><li><strong>Body Attributes: </strong>We <em>could</em> define the attributes on the body of our HTML components. Since this will become the ShadowRoot, it seems like a good option, too.</li><li><strong>Events</strong>: We <em>could</em> use events where we would publish the component’s attributes once it’s instantiated. Doesn’t seem to be quite right, but JavaScript would of course be an option.</li></ol><p>For my proof-of-concept I went with <strong>attributes on the &lt;body&gt;</strong> tag. So any attribute defined here will be used for the custom element definition later.</p><p>Inside our HTML component, we can listen for events when attributes change. This is the standard way to communicate between components and is the <strong>substitution</strong> for <em>attributeChangeCallback()</em>. This also means, that we can technically listen for any attribute change.</p><p>Vice versa, when our component changes some attribute, it can notify the hosting component about the change. For that we can use <em>CustomEvents</em> with a <em>details</em> payload.</p><h4>CSS</h4><p>Our component will be instantiated with a <em>ShadowRoot</em>.</p><p>This is such a good feature because it means we don’t have to worry about our component having any impact on the outside context. On the other hand, if we want to impact the styling of the HTML component itself, we can use CSS Custom Properties.</p><p>We can e.g. use a Custom Property for our text and background colors and also provide a fallback value. We can then define these Custom Property values on the outside context. Since the ShadowRoot comes with a {mode: &quot;open&quot;}, these values will be able to affect the HTML component.</p><p>We will skip other specifics of style inheritance related to Custom Elements to keep things short.</p><h4>JavaScript</h4><p>When we write JavaScript inside our HTML component, we can work with the document as we’re used to. There’s only one magic thing that happens behind the scenes: When you import the HTML component, any use of “document” inside your component will refer to the ShadowRoot. This is not only logical, but also means that the component won’t mess with document that it is embedded in. You still can interact with the outside context, but instead of using “document” directly, you might want to use events to keep things nicely encapsulated.</p><h4>Okay… so how do I import HTML components?</h4><p>Okay, we need a small JavaScript runtime for this. But don’t worry. You don’t have to install a library. You also don’t have to include it from a CDN (although you can!).</p><p>We’re talking about 50 lines of code and less than 1 KB. We could go through it line by line, but I’ll reserve that for another post.</p><p>There’s another reason, why I didn’t make this a “library”: I don’t think this is safe to use. I’m not a web security expert at all and I hope that informed readers will educate me and challenge the approach. What I describe here may not be safely possible in user land.</p><p>But maybe browsers could implement something like this. Who knows. I still think you can use this as long as you know what you’re importing (ideally, your own components). As soon as you’d import Third Party code, you should be aware that anything can happen, like in Node.js where we naively install code with dependencies we have no control over…</p><h4>Where to go from here</h4><p>This is rather a proposal than a final solution. The proof of concept doesn’t cover edge cases like missing component names, etc. — but it works and covers the “happy path”.</p><p>Maybe this whole idea is nuts and won’t fly. Or maybe it inspires people who work on browsers to not just focus on new syntax and JavaScript. Maybe there has been something in front of us all along that we forgot about: HTML.</p><p><strong>Read my proposal with code and examples here:<br></strong><a href="https://gist.github.com/getflourish/a87b990265db8fc243c897f34d32f860">https://gist.github.com/getflourish/a87b990265db8fc243c897f34d32f860</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=10440432390e" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Scraping and migrating a website’s content to Statamic CMS]]></title>
            <link>https://medium.com/@getflourish/scraping-and-migrating-a-websites-content-to-statamic-cms-2f97ccb20277?source=rss-303939833494------2</link>
            <guid isPermaLink="false">https://medium.com/p/2f97ccb20277</guid>
            <dc:creator><![CDATA[Florian Schulz]]></dc:creator>
            <pubDate>Tue, 11 Feb 2020 08:23:08 GMT</pubDate>
            <atom:updated>2020-02-11T08:23:08.667Z</atom:updated>
            <content:encoded><![CDATA[<h4>Moving content from a database to files</h4><p>When redesigning a website or simply moving to a new CMS, migrating content is a core task. If you or your client authored hundreds or thousands of article over years, there is no way that you can migrate those by copy &amp; pasting from one CMS to another.</p><h4>No more database</h4><p>If your old CMS had a database and your new CMS doesn’t, you need to figure out a way to migrate content from database tables to folders and files. In my case, I didn’t even have access to the database (neither did I want to mess with Drupal anyway).</p><h4>Migrating without database access? Scrape it!</h4><p>The good news was that each page on the website output a lot of structure meta data and the content was formatted as simple paragraphs with nothing fancy in between.</p><p>Given the structure of the HTML, it seemed very reasonable to migrate content by first scraping it from the website.</p><ol><li>Scrape the content from the website</li><li>Format the content and meta data to match the new content structure</li><li>Generate Markdown files</li></ol><blockquote><strong>Why scraping?</strong></blockquote><ul><li>Need to migrate a website to a flat file CMS, like <a href="https://statamic.com/">Statamic</a> or <a href="https://getkirby.com/">Kirby</a></li><li>No access to the original database of a website</li><li>No knowledge of the current CMS</li><li>No easy way to export from the current CMS</li><li>No way to import content into a flat file CMS other than creating files</li></ul><blockquote><strong>Why not use the Statamic Importer?</strong></blockquote><p>While the <a href="https://docs.statamic.com/importer">importer</a> can handle a collection of JSON content and generate entries from it, it has a drawback:</p><ul><li>no support for multi-lingual content</li></ul><h3>Statamic on Twitter</h3><p>@getflourish Ahh, the importer doesn&#39;t support multi-lingual. It&#39;s possible to add support for it, but new features are slow in coming for v2 as v3 is right around the bend. 🤔</p><p>In my case, it was necessary to import entries in German and French, thus I had two options:</p><ul><li>use my poor PHP skills to hack around with the importer to support multiple languages</li><li>generate .md files and copy them to the content folder (one folder per language)</li></ul><h4>Scraping</h4><p>Without this library for NodeJS, this project would have not been possible. The <strong>sitemap-generator</strong> is intended to generate a XML Sitemap for a website and does so fairly well! Simply pass it a base URL and start the generator.</p><p><a href="https://github.com/lgraubner/sitemap-generator">lgraubner/sitemap-generator</a></p><pre><em>const</em> SitemapGenerator = require(&quot;<em>sitemap-generator</em>&quot;);<br><em>const</em> baseUrl = &quot;<em>https://your-base-url.com/some-path</em>&quot;;</pre><pre><em>const</em> generator = SitemapGenerator(baseUrl, {</pre><pre><em>  stripQuerystring</em>: <em>false</em></pre><pre>})</pre><p>In order to generate the sitemap, the script crawls the entire website with all the links between the pages.</p><p>But instead of waiting for the script to finish and output the XML, I’ve used the callback function every time a new link is being added to the sitemap.</p><pre>// register event listeners</pre><pre>generator.on(&#39;add&#39;, (url) =&gt; {<br>  // new link found<br>});</pre><h4>Parsing</h4><p>Now, whenever we receive a new URL, we can fetch the URL and wait for the response which will be a string of HTML.</p><p>Using the library JSDOM we can then turn the string into a in memory document object model (DOM) that acts like a real DOM.</p><pre>// Construct a new in-memory DOM from the HTML string<br>let document = new jsdom.JSDOM(htmlString).window.document;</pre><p>This allows us to use <em>querySelectors </em>etc. to parse anything from each document. For example <strong>meta-tags, title, body content, …</strong></p><p>For example, to receive the meta description, we can use:</p><pre>document.querySelector(&quot;<em>meta[name=&#39;description&#39;]</em>&quot;).content;</pre><p>When querying actual HTML content, such as an article, we might want to strip some of the HTML. We could:</p><ul><li>use innerText and remove any HTML / formatting</li><li>use innerHTML and convert it to Markdown</li></ul><p>The benefit from converting to Markdown is that line breaks and some formatting like bold, italic and headings are preserved.</p><p>I’ve used <em>Turndown </em>for this task.</p><p><a href="https://github.com/domchristie/turndown">domchristie/turndown</a></p><pre><em>var</em> TurndownService = require(&quot;<em>turndown</em>&quot;);</pre><pre><em>var</em> turndownService = <em>new</em> TurndownService();</pre><pre><em>let</em> node = document.querySelector(&quot;<em>article</em>&quot;);</pre><pre><em>let</em> markdown = turndownService.turndown(node.innerHTML);</pre><p>From all the queried information, we can then construct objects for each URL:</p><pre>let data = {<br>  url,<br>  title,<br>  description, <br>  markdown,<br>  ...<br>}</pre><p>And ultimately collect all those chunks of data in an Array or Object which we can save to disk once the scraper is done.</p><pre>fs.writeFile(output, JSON.stringify(collection), <em>function</em>(<em>err</em>) {<br>  <em>if</em> (err) {<em>return</em> console.log(err);}<br>  console.log(&quot;<em>The file was saved!</em>&quot;);<br>});</pre><h4>Transformation</h4><p>Okay, it’s simple to get the data as <em>JSON</em>. But some flat file content management systems require markdown files in <em>YAML</em> format.</p><p>Fortunately, there is JS-YAML for that.</p><p><a href="https://github.com/nodeca/js-yaml">nodeca/js-yaml</a></p><p>Using this library, we can reformat the JSON to match the intended structure and then write individual files for each entry of the original collection.</p><pre>yaml.safeDump(entry, { <em>lineWidth</em>: <em>Infinity</em> });</pre><p>I’m not sure anymore if the <em>lineWidth</em> parameter is required, but it can help to avoid unnecessary line breaks when converting text to YAML.</p><h4>Strip whitespace, control characters, etc.</h4><p>When copy &amp; pasting content from PDF to a CMS, editors might actually copy invisible control characters. While invisible to the reader, a converter like JS-YAML might get into trouble.</p><p>From my experience, it meant that paragraphs and new lines where output as literal “\n” which is not how a human would make a new line in markdown. I did ran a few regex before converting to YAML.</p><p>For example to replace some invisible whitespace with nothing:</p><pre>processedText.replace(/<em>•</em>/<em>g</em>, &quot;&quot;);</pre><p><em>Note: The • character is used to represent an actual invisible character.</em></p><p>I’ve tried some Regex ranges to only include visible ASCII characters but ultimately ended up manually creating rules for all the unwanted characters I could find in my content files.</p><h4>Generating Markdown files</h4><p>I then saved all the files with a specific format using the original publish date and slug.</p><p>German entries went into the root of the folder, French entries into a “fr” subfolder.</p><p>It was important that I both files shared the same UUID. For Statamic this must be a UUID/4.</p><h3>Florian Schulz on Twitter</h3><p>@statamic Okay, got it. The Index seems to get really confused when manually adding collection files using ids other than uuidv4. is_id() insider helpers.php and PathTags.php are responsible, probably for a good reason.</p><p>Once I figured out that I can’t just use any ID (like “123”), I simply switched to assigning each entry a UUID.</p><p><a href="https://github.com/kelektiv/node-uuid">kelektiv/node-uuid</a></p><pre>const uuidv4 = require(&#39;uuid/v4&#39;);<br>uuidv4(); // ⇨ &#39;1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*PxgKEiGNcOiS0IBxtsGvzQ.png" /></figure><p>After running the script, it generated hundreds of markdown files, neatly organized in one folder per language, ready to import!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/816/1*beDqDZbyASdnvECwCG3_NA.png" /><figcaption>Generated Content files. Left: German, Right: French. Filename convention for both languages: YYYY-MM-DD.slug.md (identical file name, but this might not be required since the UUID inside the file is responsible for the mapping)</figcaption></figure><h4>Summary</h4><p>While there aren’t many steps and code involved, there were a few details that I had to figure out along the way. Once I had a nice big chunk of JSON with all the content, it was clear to me that this could be transformed into any structure required by the CMS.</p><p>I initially hoped that the Importer could do its magic by feeding it the JSON, but it turned out that it didn’t support multi-language content. Thus, I had to re-format the data, convert it to YAML and mess around with hidden white space, control characters and the like, but finally it worked out!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2f97ccb20277" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Getting the most out of Angular: Hot Module Replacement, Two way data binding for Custom…]]></title>
            <link>https://medium.com/@getflourish/getting-the-most-out-of-angular-hot-module-replacement-two-way-data-binding-for-custom-8ecfe702e8db?source=rss-303939833494------2</link>
            <guid isPermaLink="false">https://medium.com/p/8ecfe702e8db</guid>
            <category><![CDATA[angular]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[vuejs]]></category>
            <dc:creator><![CDATA[Florian Schulz]]></dc:creator>
            <pubDate>Thu, 04 Apr 2019 05:23:05 GMT</pubDate>
            <atom:updated>2019-04-08T15:20:02.085Z</atom:updated>
            <content:encoded><![CDATA[<h3>Getting the most out of Angular: Hot Module Replacement, Two way data binding for Custom Components and more</h3><h4>Based on my experience with Vue.js</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*BkcZErhlTwFT4wxdYQ4h1w.png" /></figure><h4>Preface</h4><p>I’ve been designing and developing components with Vue.js for the past 4 years and I’m really happy with it as it helps me to build prototypes and web apps in a fast and sane way.</p><p>When I recently started designing components with Angular, I knew that I had to expect more verbose code, boilerplate and not so great performance in general. The templating syntax has some quirks, but most of it comes down to “getting used to it”.</p><p><strong>Syntax in Vue</strong><br>v-model, v-on:click, v-bind:class, v-for, v-if</p><p><strong>Syntax in Angular</strong><br>[(ngModel)], (click), (class), *ngFor, *ngIf</p><p>The differences in the JavaScript part (module, component etc.) are bigger since Angular makes use of TypeScript, Classes, Decorators, Services, etc. and Vue is more or less a single JavaScript Object with some conventions.</p><p>But besides the things that exist in both frameworks in different ways, I’ve found some things that I had grown used to when working with Vue, that took me a while to figure out because they are not documented or a core feature of Angular.</p><ul><li>Hot module replacement</li><li>Dynamic component rendering</li><li>Transparent wrapper components</li><li>Forwarding element attributes from the host component to a child</li><li>Two way data binding with ngModel on custom components</li></ul><h4>Hot module replacement</h4><p>When starting a new project via the vue-cli, hot module replacement is enabled out of the box. This is a massive improvement to the development experience and velocity. When making changes to code, instead of reloading the page manually, all state is maintained, style changes are applied in an instant, the page remains its scroll position, dialogs remain in their opened state, … 😍</p><p>Unfortunately, the Angular CLI does not ship with <em>Hot Module Replacement</em>. While in theory there is an option baked in to enable it, the actual activation requires quite some configuration in a variety of files and dependency on a 3rd party npm package. It’s not difficult to enable, but requires a new environment setup. 😫</p><p>Figuring out how to do this wasn’t easy either. It’s not like there is official doumentation on the Angular website for it. To make it easier for you, here is it, the guide to implementing Hot Module Replacement in Angular projects: <a href="https://github.com/angular/angular-cli/wiki/stories-configure-hmr">https://github.com/angular/angular-cli/wiki/stories-configure-hmr</a></p><p>I think a lot of Angular developers are missing out on that feature that other frameworks, like Vue.js have built in. While I successfully implemented <em>HMR</em>, the experience is not quite like what Vue.js has to offer. <a href="https://stackoverflow.com/questions/49595833/how-to-preserve-state-during-hmr-using-angular">Maintaining state</a> is something you still would need to figure out yourself and CSS changes will still cause a re-compilation. This takes extra <a href="https://webpack.js.org/guides/hot-module-replacement/#hmr-with-stylesheets">configuration</a> and <a href="https://github.com/angular/angular/issues/11942">guides</a> with issues to get it to work 😅</p><p>Out of the box, Angular makes frontend design quite hard. Longer compile times, no state persistence, hard reloads of the page add a lot of friction. 😢</p><h4>Dynamic component rendering</h4><p>When dynamically rendering components, for example from a JSON representation of a nested component structure, Vue.js shines because it has the “is” attribute. One can pass in a component name that matches some imported component and it will render as such. 😎</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*65bGhzmiLy1oezYf6qlmGg.png" /></figure><p>This allows you to render dynamic interfaces based on structured data, such as forms etc.</p><p>While Angular can do this, too, you need to write more code, using <em>ComponentFactoryResolver, </em>methods and whatnot 😫 It could be so simple!</p><p><a href="https://angular.io/guide/dynamic-component-loader">https://angular.io/guide/dynamic-component-loader</a></p><h4>Custom components with Two-way data binding</h4><p>In Vue you can simply <strong>$emit </strong>a change event or input event from a custom component to enable v-model support. If you want to use ngModel on a custom component in Angular you need to implement an interface called <em>ControlValueAccessor </em>and a few more methods.</p><p><a href="https://rangle.io/blog/angular-2-ngmodel-and-custom-form-components/">https://rangle.io/blog/angular-2-ngmodel-and-custom-form-components/</a></p><h4>Transparent wrapper components</h4><p>Since components in Vue can be defined in a template tag, you can easily create custom components that simple wrap single native elements, such as a button component that consists of a button but with an extended API (props, states, …). Vue will then only render that native button, and won’t show the custom component name in the DOM.</p><p>Angular on the other hand seems to render the custom component and the internals. This means, that you end up with a wrapper component and the native components.</p><p>This is probably the reason why Angular Material implements buttons using attributes, such as: <strong>&lt;button matButton&gt;. </strong>While this makes sense to avoid bloating the DOM, it also make the API inconsistent. Some components are implemented using attributes, some using custom selectors…</p><h4>Forwarding element attributes from host to child</h4><p>When creating components that are composed of native elements, such as button, input, etc. it can be useful if the custom component can immitate a native component.</p><p>For example a custom component might want to behave similar to it’s native pendant:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*F79eIDCqmYOVXN5THXP-VQ.png" /></figure><p>By default, Vue.js binds all attributes from the custom component instance onto the outer element of the component. In the case of the range slider, the component only exists of one element, this the input will receive all the attributes. Great! No need for custom API / props, because the native attributes do all the work for free! 👌</p><p>This gets more tricky, given a search field that should have a search icon and a loading spinner included. We could design a custom search component like this in Vue.js:</p><p><strong>&lt;custom-search v-model=“query” disabled /&gt;</strong></p><p>or in Angular like this:</p><p><strong>&lt;custom-search [(ngModel)]=“query” disabled /&gt;</strong></p><p>Implemented as a component in Vue like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/990/1*vl4m7ZccmmFO4RaTgs0KCA.png" /></figure><p>Unfortunately, Vue needs a single child inside a component which is why the above example wraps everything in a div. Angular doesn’t, which is nicer. So you can easily create such a component template in Angular:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/670/1*3cr2V4z0cD5TWuPgaA39Bw.png" /></figure><p>This component would result in an input with an icon displayed in front of it and a loading indicator after it (given the required CSS). To be able to control the custom-search like a normal input field, the Vue.js implementation can pass on all attributes onto the input field using <strong>v-bind=“$attrs”.</strong></p><p><strong>&lt;input type=“search” v-bind=“$attrs” /&gt;</strong></p><p>In that way, all the attributes from the &lt;custom-search&gt; will be applied to the nested input field. Cool! 🕹</p><p>In Angular it is not so easy and you actually need to implement code that copies all the attributes from the host component <em>OnInit</em>. 😫</p><p><a href="https://stackoverflow.com/questions/43785547/angular2-passing-all-the-attributes-to-the-child-component">https://stackoverflow.com/questions/43785547/angular2-passing-all-the-attributes-to-the-child-component</a></p><p>There are many more details that are more complicated to setup in Angular but at the end of the day most things work out.</p><p>I definitely prefer the simplicity of Vue.js when it comes to component design and frontend performance. But in practice the frameworks don’t differ too much anyway.</p><p>Vice versa, Angular shows the power of TypeScript and makes development much easier/safer. Can’t wait to benefit from this with the upcoming Vue.js 3.0 written in TypeScript 🍭</p><p>If something I wrote about doesn’t make sense or there are better ways to deal with the described drawbacks, please share your thoughts. I found it quite hard to find code examples, also because the terminology in Angular is different than it is in Vue, React, etc. 🕵️‍♂️</p><p>Switching from Vue to Angular is probably rare (<a href="https://stateofjs.com/">https://stateofjs.co)</a> but sometimes you have to work with what you’ve got. Designing good component design applies to any framework and ultimately the differences aren’t that big. I was afraid to check out Angular at first, but realized, it’s not so bad as I had expected.</p><p>I will certainly prefer Vue over Angular, but with so many languages and frameworks available, it’s always good to look beyond the tellerrand.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8ecfe702e8db" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Designing with Ratio]]></title>
            <link>https://medium.com/@getflourish/designing-with-ratio-dcc656d5385d?source=rss-303939833494------2</link>
            <guid isPermaLink="false">https://medium.com/p/dcc656d5385d</guid>
            <category><![CDATA[design]]></category>
            <category><![CDATA[web-design]]></category>
            <category><![CDATA[css]]></category>
            <category><![CDATA[typography]]></category>
            <category><![CDATA[web-development]]></category>
            <dc:creator><![CDATA[Florian Schulz]]></dc:creator>
            <pubDate>Sun, 21 Oct 2018 13:38:52 GMT</pubDate>
            <atom:updated>2018-10-24T06:56:48.082Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*HNi6AT5ZlQizR9Xyts318g.png" /></figure><p>Two years ago, I published “<a href="https://medium.com/@getflourish/designing-with-intent-be6664b10ac">Designing with Intent</a>” in which I wrote about design tools that can capture the intent and relationships of a design in addition to mere properties and values.</p><p>Back then, I used methods like “interpolation” and concepts like “contrast” to describe a way of thinking and designing in extremes — between <em>minimum</em> and <em>maximum</em> states.</p><p>Instead of tweaking a dozen different font sizes for headings and body copy, one could <strong>define the base font size and scale factor </strong>that control the hierarchy between all of them.</p><p>Instead of tweaking text color and background color individually, one could <strong>define the desired contrast</strong> between them.</p><p>Instead of tweaking line spacing, font sizes, font weights, letter spacing, etc. for different screen sizes, one could <strong>define the relationship</strong> between those properties and have them dynamically adjust.</p><p>In the meantime, I took those concepts further and turned them into a web design tool, aimed at helping design for the browser, in the browser. With <em>Ratio, </em>I’m trying to turn my knowledge about design, writing CSS and creating design systems into a series of tools that enable both designers and developers to explore more and worry less.</p><p>This article explains some of my thinking behind <em>Ratio </em>and introduces some aspects of the interface in greater detail.</p><p>But before I go into that, I want to elaborate a little bit on design and programming and the popular question “Should designers code?”</p><h4>Programming design</h4><p>I think programming can be part of a design process, but it should not require switching to a text editor to do so. Creating abstractions and establishing intentional relationships are concepts that are too powerful to stay outside of a designer’s toolbox. They enable working with a dynamic medium and taming the uncontrollable.</p><p>The concepts that I wrote about two years ago actually don’t require a lot of code. But they do require fiddling with your text editor in order to fine tune values by typing numbers. They require getting out of the design tool in order to design.</p><p>In his genuine book “<a href="https://abookapart.com/products/flexible-typesetting">Flexible Typesetting</a>”, Tim Brown wrote:</p><blockquote>Your design tool is working against you. It is stuck in the traditional mindset of absolute measurements. This is precisely one reason why people very good at web design argue that designers should learn to write code. No mainstream design tools — and I work for a company that makes mainstream design tools — are completely appropriate for the practice of typesetting today. Some of the smartest people I know are building more appropriate tools, but for now you’ll need to make design decisions by writing and testing code. — <strong>Tim Brown, Flexible Typesetting</strong></blockquote><p>I fully agree and believe that a way to express and use more dynamic and flexible design concepts in an actual design environment would be beneficial for many people. It would be a lost oppurtunity for designers to leave those techniques up to developers to figure out how to <strong>implement design</strong>. Instead, we could be using aspects of programming — variables, interpolation, functions — <strong>to actually design.</strong></p><p>If we utilize dynamic units, calculations and formulas, we can start to take back control over the web as a design medium. When we let go of the static mindset that comes with pages and artboards — fixed snapshots of an inherently dynamic medium — we can start to embrace the real potential of the web.</p><p>We can start to actually design interactivity. We can do the exciting work that’s all too often left to the developer’s interpretation. We can start to think in terms of intention and abstraction. When we think about web design, we need to think about the whole system and how things relate to each other.</p><blockquote><strong>It’s about the relationships, the boundaries, the extremes, and everything in between.</strong></blockquote><p><strong>But in order to do so, we need tools to free our mind</strong>. We need tools that get out of the way. We need tools that allow us to design at the speed of thought. We need tools that are fluid and adapt. We need tools that suit us. Thus, we need to shape our own tools so that they can shape our work.</p><h3>Introducing: Ratio</h3><p>Instead of waiting for others to build a better design environment, I’ve created it myself. It’s called <em>Ratio. </em>It combines <em>modular scales, fluid typography, color transformations, design tokens</em> and the <em>layout power</em> of modern browsers.</p><blockquote>Ratio equips designers with the same tools and concepts that developers use to implement complex design systems. Take creative control over typography, color, time and space by using variables, scales and functions. By appreciating the abstract and rationale, designers get the chance to explore more and worry less. Discovery instead of pixel pushing.</blockquote><p>Under the hood, design in <em>Ratio</em> is powered by <strong>CSS</strong>. Thus, you can do everything that CSS can do. It’s certainly not the first tool doing that, but my approach is to be slightly more transparent about the underlying code and utilize it. If you want, you can always do some hand-coding in between.</p><p>But more importantly, <em>Ratio</em> provides interfaces that help you <em>work with </em>CSS without actually writing it. It helps you to <strong>visualize your design system</strong> and create abstractions when you want to. It’s my personal take on the <em>web inspector</em>. I love web inspectors and what they can do. But what I want is a <em>web creator</em>.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fplayer.vimeo.com%2Fvideo%2F295041731%3Fapp_id%3D122963&amp;dntp=1&amp;url=https%3A%2F%2Fvimeo.com%2F295041731&amp;image=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F732092738_1280.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=vimeo" width="1920" height="1080" frameborder="0" scrolling="no"><a href="https://medium.com/media/b307f88d741acd7915505a22d0d17ca6/href">https://medium.com/media/b307f88d741acd7915505a22d0d17ca6/href</a></iframe><h4>The power of CSS</h4><p>Building a tool on top of CSS comes with a lot of built-in responsive design features. Just think about all the <strong>relative size units</strong> that you can work with: %, em, rem, vh, vw, and many more that enable us to encode relationships for dynamic design systems.</p><ul><li><strong>%</strong> — a fraction of the element’s parent’s width</li><li><strong>em</strong> — a size relative to the element’s font size</li><li><strong>rem</strong> — a size relative to the root element’s font size</li><li><strong>vh</strong> — a fraction of the viewport’s height</li><li><strong>vw</strong> — a fraction of the viewport’s width</li><li><strong>vmax</strong> — the larger value of either the width or height of the viewport</li></ul><p>Modern browsers support almost <a href="https://codepen.io/getflourish/pen/8a6a2b2d00d2f282cd6cfe1f24c953bd">500 CSS properties</a> and CSS has become more and more powerful in recent years. One of the most recent additions, <strong>CSS Grid,</strong> introduces new units like <em>fr</em> (fraction), and functions like <em>calc, repeat, min, max </em>and<em> minmax</em> help to create<em> </em>flexible layouts.</p><p>With <strong>web fonts, OpenType features, media queries, flex-box, grid, transitions and animations</strong> we have all the styling possibilities needed to create beautiful interfaces.</p><p>Of course, for some things you’ll be better off using <strong>Canvas, WebGL or Shaders</strong> — but CSS on its own can do a lot. And with ambitious projects like <a href="https://developers.google.com/web/updates/2016/05/houdini">Houdini</a>, we might be able to invent new CSS properties which could turn CSS into an even more universal way to describe design with almost endless possibilities.</p><h4>Auto-complete for design</h4><p>Unfortunately, CSS is still a big black box to many since there are so many properties available and some properties are tedious to type. The good news: <em>Ratio</em> knows about all those properties and auto-completes them for you. It also provides abbreviations for the most commonly used properties, so you can just type “ff” to find “font-family”. Developers may know this from <a href="https://docs.emmet.io/css-abbreviations/">Emmet</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/482/1*J0aEI6fBLycDZp3e2ZoT5w.gif" /></figure><p>Another complexity of CSS is that all properties have default values, that you need to override to achieve your desired style. In order to figure out those default values, it’s often necessary to use the web inspector (think: default form element styles).</p><p><em>Ratio</em> shows you those computed values right away — and you even learn about the default values. Did you know that the default <em>text-align</em> value is not “left”, but “start”? I didn’t, but it makes sense in order to support right-to-left languages.</p><p>The inspector interface also encourages you to re-use defined values, by offering you auto-completion. Even though your code editor may already be smart enough to collect defined properties, in <em>Ratio</em>, you will actually see the <strong>values that are meant to be re-used</strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/966/1*coKhx36sZWtnEwdnMz1lkQ.png" /><figcaption>Box-shadow design tokens within the CSS inspector.</figcaption></figure><h4>Design tokens</h4><p>For many years, web developers have been using pre-processors like Sass or Less to extend the capabilities of CSS. A main feature that came with those were <em>variables. </em>This fundamental programming concept allowed developers to write more maintainable code. Variables have been useful to store <strong>color values, breakpoints, spacing values, timing values and typographic features</strong>.</p><p>With the rise of <strong>design systems</strong> on the web, re-using design properties has also arrived in the mindset of product designers. <em>Design tokens</em>, as popularized by <a href="https://twitter.com/jina?lang=de">Jina Anne</a> (former Salesforce, <a href="https://www.lightningdesignsystem.com/design-tokens/">Lightning Design System</a>), are especially useful in the context of theming.</p><p><em>Ratio</em> allows for the creation of variables in form of design tokens. <strong>Collections of design tokens </strong>can be created for any property: <em>color, font-size, margin, box-shadow, border-radius</em>, … really anything. By creating design tokens, you provide meaningful names to values. Those names will then be available and searchable in <em>Ratio’s</em> CSS inspector.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_ROi-54Oz7lFa1xb2YzzSA.png" /><figcaption>The library shown design tokens for various properties. Shown here are colors.</figcaption></figure><p>Being able to save common values for individual style properties is a fundamental tool for maintaining consistency, enables re-use of design systems, theming and is also a really fast way to style — by using the name of a design token instead of typing long and cryptic values over and over again. Naming becomes a design tool, rather than an afterthought in development.</p><h4>Fluid Typography</h4><p>While design tokens can be added manually, they can also be generated, scaled and interpolated across breakpoints. This enables the setup of <a href="https://www.modularscale.com/">modular scales</a> and <a href="https://www.madebymike.com.au/writing/precise-control-responsive-typography/">fluid typography</a>. Instead of messing with individual font sizes of paragraphs, headings, blockquotes etc., you simply define base font sizes and scale ratios and let interpolation do the rest.</p><p>What may sound complicated and require some initial understanding of the concept, results in a very powerful mechanism to work with type that can be controlled by a few values and sliders. <em>Ratio</em> helps here by providing an interface to otherwise complex CSS formulas or Sass mixins.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5peMrzZSFF3iHg_-e-pSoQ.png" /><figcaption>Setting up modular Scales in Ratio that can help with responsive typography. Font sizes can scale fluidly and you can control a whole layout by adjusting a few settings and ratios.</figcaption></figure><p>Note: Setting up fluid type isn’t a special concept that only works for font sizes, but it’s a universal mechanism of programming design with <em>Ratio</em>. The interface applies to any property and can be useful for line spacing, margins, paddings, colors, shadows and more.</p><h3>Inspectors in Ratio</h3><p><em>Ratio</em> doesn’t try to just give you a single all-purpose design inspector, but instead offers multiple <strong>different perspectives on code</strong>. That way, <em>Ratio</em> supports both sides of web design: exploration and engineering. With <em>Ratio</em>, you are in full control over individual properties, but you are also able to set up systems that orchestrate more than one thing at a time.</p><h4>Color Canvas</h4><p>For example, the <strong>color canvas</strong> visualizes connections between colors and can be used to transform from one color into another. As known from CSS pre-processors, colors can be <em>darkened</em>, <em>lightened</em>, <em>shifted in hue</em>, <em>desaturated</em> and more. Those are powerful mechanisms not only for developers that want to write less code, but also for designers that want to explore color combinations and design with theming in mind.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*s6MU__PIo58QdGxe59fPcw.png" /><figcaption>The canvas shows a base color (blue), a hue-shifted color (yellow) and a darker blue color used for the card on the bottom.</figcaption></figure><p>The <em>color canvas</em> might not be needed for smaller projects, but certainly shines with complex ones.</p><p>Complex systems, such as operating systems or business applications, may use several levels of color abstraction. For instance, MacOS recently introduced Dark Mode and encourages developers to use their color variables found inside <a href="https://developer.apple.com/documentation/appkit/nscolor">NSColor</a>. A different example with five levels of abstraction is <a href="https://www.nylas.com/">Nylas Mail</a> that can serve as an inspiration for setting up colors in <em>Ratio</em>.</p><p>In any case, the color canvas can be a great way to explain color systems to collaborators who would otherwise need to imagine it by reading source code or by building a style guide. With <em>Ratio</em>, visualizations that are often left to documentation become actual tools.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ETMSo5Bt9q2nI5yYmq9hdQ.png" /><figcaption>Initial concept of showing color relationships between palettes. The UI for creating this inside Ratio today (screenshot above) looks different, but the concept remains the same.</figcaption></figure><h4>Driver Inspector</h4><p>Another example of visualization of code is the <strong>driver inspector</strong>, an interface that works similar to a timeline in video editing tools. In addition to time, it can be used to manipulate values based on other variable inputs such as <strong>window size</strong> (breakpoints), <strong>scroll position</strong> (parallax scrolling), <strong>mouse position</strong> and more.</p><p>Each selector is shown with tracks for each property that has changing values. You can use the driver inspector to add, remove and move keyframes or change their corresponding values. It’s a simple way to see what is otherwise hidden in multiple places in your source code.</p><p>Credit where credit is due, <a href="http://principleformac.com/">Principle for Mac</a> has been the main inspiration for using a timeline interface for more than just <em>time</em>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8Vkr7tEu0G5tBvoDq9Nb4A.png" /><figcaption>The driver inspector shows the change of values across breakpoints, time, scroll position and other variable inputs.</figcaption></figure><h4>CSS Inspector</h4><p>When you select a layer in <em>Ratio</em>, you can see its related CSS declarations in the CSS inspector. That way, you have full access and control over styles — no limits. It’s like writing CSS to a file. But, compared to text editors, <em>Ratio</em> filters out the noise of other selectors so that you don’t need to scroll, jump and search around in your CSS files.</p><p>While showing you less, it also shows you more: The inspector highlights use of variables (design tokens), groups breakpoints per property and shows related selectors, such as hover states.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*0eSlqRmLf1IZAzdE4p7FNw.png" /></figure><p>When you want to create a new rule for an existing selector, the inspector searches through all the existing selectors. When you type a selector that has already been defined, <em>Ratio</em> will enter the selector instead of creating it again. The interface prevents you from making unnecessary duplications. It’s like appending new CSS rules to the end of a file but the computer’s automatically cleaning up for you.</p><h4>Style Dial</h4><p>The style dial is the gestural counter part to the CSS inspector. It’s a compact interface that combines the most important aspects of typography, color and space into a radial menu. Instead of typing values, it allows you to spin/scroll values up or down while keeping your eyes on the content. The contextual menu has been designed for freestyle design exploration without constraints.</p><p>Since it supports keyboard shortcuts to switch between properties, tweaking font size, line height, letter spacing can become a fluid process of scrolling up/down and switching between tools using the keyboard — all while staying focussed on the actual text layer.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*FgonH55zEC34CfXD-fzkuA.gif" /><figcaption>The style dial controls the line height, font size and font weight by scrolling up/down. Using the mouse to change values and keyboard to switch between properties is a fluid and precise way to control numeric values.</figcaption></figure><h3>Extensibility</h3><p>While <em>Ratio</em> already offers many different perspectives and interfaces on CSS, there are many more possibilities and web developers have already built tools for specific tasks.</p><p>CSS gradient generators, border radius tools, grid builders, color palette generators, modular scales, font pairing tools, … there will always be the need and desire to build custom interfaces and features. Thus, it is important to me that Ratio can be extended and that for instance design tokens can be generated by external tools.</p><p>To illustrate this, here’s an integration of the <a href="https://codepen.io/meodai/pen/RerqjG"><strong>harmonious color palette generator</strong></a> by<strong> </strong><a href="https://twitter.com/meodai?lang=de"><strong>meodai</strong></a><strong>. </strong>David is an expert when it comes to color systems and he’s built dozens of different interfaces to work with color. Using a simple mechanism, his existing web app can hook into <em>Ratio</em> and provide colors for it.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/965/1*x1HwbUTgTZfvjT22wruS8w.gif" /><figcaption>Meodai’s harmonious color palette generator in sync with Ratio.</figcaption></figure><p>I want <em>Ratio</em> to provide the core tools on its own, but being an active <a href="https://github.com/getflourish/Sketch-Mate">Sketch</a> and <a href="https://useratio.com/stylemate/">Adobe XD plugin</a> developer, I think it’s important to build in extensibility right from the beginning.</p><h3>A broader understanding of code</h3><p>For now, we’re used to call code what is plain text in text files that get compiled and can run in a browser. But any form of communication is code. Any word we say, write, any image we draw, encodes information. It’s up to the other to interpret and understand.</p><p>When we start to loose our fear of the term code and programming, we can start to see behind the actual principles. The logic. The conditions. The meaning. The rules. It’s what we all work with, but often neglect. But if we embrace them, we can start to design with ratio. We need to become aware of the reasons behind our choices and decisions. And we then need the right tools to capture and express them.</p><blockquote>[…] I hope this book inspires you. You can shape the words we use. You can influence design tools and do original work. You can return to tradition and map treasured, old advice onto this new world. — <strong>Tim Brown, Flexible Typesetting, p. 205</strong></blockquote><p>While I was already deeply working on <em>Ratio</em>, reading this sentence was a great reassurance and motivation to keep moving. Thanks <a href="https://medium.com/u/451a777d0bab">Tim Brown</a>!</p><h4>The future of Ratio</h4><p><em>Ratio</em> is currently in closed Alpha with everything presented here being functional as shown in the <a href="https://vimeo.com/295041731">video</a>. In a future story I will write about technical aspects of <em>Ratio</em> and how it fits in with your existing projects and workflows.</p><p>From designers who want to design in the browser, to designers who want to simply tweak the last design details of a developed site, all the way to developers using it to setup design systems, there are many use cases that I have in mind.</p><p>If you are interested in future stories about <em>Ratio</em>, make sure to follow me here and <a href="https://twitter.com/useratio"><strong>@useratio</strong></a> on Twitter.</p><p>Sign up to be notified about the public release on <a href="https://useratio.com/"><strong>useratio.com</strong></a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=dcc656d5385d" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Turning Twitter’s Feed on its Head]]></title>
            <link>https://medium.com/@getflourish/turning-twitters-feed-on-its-head-9565af1728c8?source=rss-303939833494------2</link>
            <guid isPermaLink="false">https://medium.com/p/9565af1728c8</guid>
            <category><![CDATA[twitter]]></category>
            <category><![CDATA[social-media]]></category>
            <category><![CDATA[design]]></category>
            <category><![CDATA[ui]]></category>
            <dc:creator><![CDATA[Florian Schulz]]></dc:creator>
            <pubDate>Sun, 04 Feb 2018 12:48:45 GMT</pubDate>
            <atom:updated>2018-02-09T13:32:00.596Z</atom:updated>
            <content:encoded><![CDATA[<h4>A design that helps you to catch up with the people you choose</h4><p>Twitter and Facebook use infinite news feeds to display content. Seemingly simple, somewhat chronologically ordered, but algorithmically prioritized content of people, companies and news organizations you follow. Prioritizing and promoting content based on “relevance” is an attempt to handle the sheer amount of information being posted.</p><p>For example, the more you interact with someone or the more someone posts, the greater the chance that their tweets show up at the top of your news feed. People you never interact with or who post once a month are likely to be unseen and lost forever. Out of sight, out of mind.</p><p>Besides the filtering, the core idea still is: what’s new is more important. The newer something is, the higher up it appears in the feed. Nothing more boring than the news from yesterday. Or the last hour.</p><p>But wasn’t this supposed to be a social network? Something about people and keeping in touch? Unfortunately, it’s impossible to catch up when you are flooded by tweets, retweets, news, and spam and have no sense of start and end.</p><p>Let’s rethink the design.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*AHAJfy_HIcud0h62ApEB3A.png" /><figcaption>An interface concept that shows a list of people you follow, sorted by the date of their last tweet.</figcaption></figure><h4>Inbox everyone</h4><p>Let’s hide all content from the feed. Let’s display all the people you are following. A complete list of all the people you are interested in. Name, avatar, date of last tweet. That’s it.</p><h4>Reverse order</h4><p>Now, instead of designing this as a news feed with the latest news on top, let’s reverse the order. Someone who tweeted a month ago is shown first, someone who just tweeted, all the way down at the bottom. In my case this revealed a few people who last tweeted 7 years ago.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*YbE1sO1szgg2Rf7aEty1cA.png" /><figcaption>Left: My Twitter feed as of February 2018. A mix of (sponsored) content, text and images. Right: A list of people I follow, sorted by date of their last tweet.</figcaption></figure><h4>Archive</h4><p>Since we display all the people you are following, this would result in a very long list, and the old tweets you’ve already seen would always stick at the top. That doesn’t make sense. That’s why common news feeds don’t work this way.</p><p>But: While scrolling past people, we can mark them as “seen” and hide them until they post something again. A timestamp becomes the single filter that defines what we see or don’t see.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*72AsBqdCv93C-EdBlByu_w.gif" /><figcaption>Note the badge at the top of the interface: It shows the number of remaining people in the inbox. Pressing the “archive button” will hide everyone who’s last tweet is older than the currently displayed ones. Also shown: detail view that shows the timeline of a selected person.</figcaption></figure><h4>Time to catch up</h4><p>Instead of hunting for the latest and greatest news, we now have a design that makes sure that every single person we’re following can be seen. Now, it is our choice to skim and scroll past them. It is our choice to tap and actively view the content. We are no longer distracted by images, animated GIFs or ads. Instead, we are driven by people and our interest in what they had to say — even if that was last week.</p><h4><strong>Back to the roots</strong></h4><p>By hiding retweets, favorites and replies, the design puts emphasis back on the original thoughts that people shared with the world, valuing the rare moments that people took time and energy to write something of their own. Likes and retweets can stay in the fast food feed.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*bsjmCb8AC9FFgzWN54WLwA.png" /></figure><h4>Unfollow</h4><p>Now, you may stumble upon people who haven’t appeared in your feed in a while, you may find that some of them are not interesting to you anymore. Such an interface makes it easy to unfollow them on the go. A nice side effect.</p><h4><strong>Why is this better?</strong></h4><ol><li>You won’t miss activity from people who rarely tweet. Tweeting less doesn’t mean the content is not worth seeing. If people you care about say something, it matters.</li><li>People who tweet a lot will still show up, but never multiple times. They get one slot like everyone else. News organizations and other high frequency accounts will always be around, but not outrank the people who tweet once in a while.</li><li>It’s you doing the filtering, not the algorithm. By seeing the faces and names of people, you are likely to only look at the ones that seem relevant at this moment in time. Interested in tech? Look at the people you know work in that field. Interested in politics right now? You might look at other accounts instead.</li><li>Other than with the infinite scrolling feed, this design provides a clear start and end. We can explicitly display the number of accounts that you haven’t looked at. Transparent and finite.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/890/1*N-Z-qdtVXgq8nonK8ifLEw.png" /><figcaption>Empty state when everything has been seen and archived.</figcaption></figure><h4>But isn’t this… stressful?</h4><p>You might think that this design would make you want to look at every single person’s recent tweet in order not to miss anything. Or to scroll to the bottom to see the most recent news. If you follow hundreds or thousands of people, yes, that would be a lot of work. But here’s the thing: by hiding distracting content and focusing on people, this design doesn’t entice you to look at everything and instead encourages you to choose consciously. I think that Twitter should not just be about news. It should also enable you to see what friends and colleagues, who are neither hyper active nor famous, share with the world.</p><h4>Demo</h4><p>Want to give it a try? Sign in with your own Twitter account to explore this concept. You can view all your followers, read their most recent tweet and tap into their timeline to read more. The site also remembers where you’ve left off, so that next time you visit, you can continue at the same point in time.</p><p>👉 <a href="http://www.florianschulz.info/twitter">www.florianschulz.info/twitter</a></p><h4>Conclusion</h4><p>I don’t see this as the one and only view that is better than a personalized feed. But it is another way to look at content. Maybe users could choose their own priority: be it latest news, or the things people had to say. The latter may be more work and less entertaining. But it might be more meaningful and helpful to stay in touch with the people we chose to follow.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9565af1728c8" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[From Mobile to Desktop: Cross Device Communication using WebSockets]]></title>
            <link>https://medium.com/@getflourish/from-mobile-to-desktop-cross-device-communication-using-websockets-f9c48f669c8?source=rss-303939833494------2</link>
            <guid isPermaLink="false">https://medium.com/p/f9c48f669c8</guid>
            <category><![CDATA[design]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[apps]]></category>
            <category><![CDATA[nodejs]]></category>
            <category><![CDATA[web-development]]></category>
            <dc:creator><![CDATA[Florian Schulz]]></dc:creator>
            <pubDate>Fri, 08 Dec 2017 19:14:49 GMT</pubDate>
            <atom:updated>2017-12-11T10:05:41.307Z</atom:updated>
            <content:encoded><![CDATA[<h4>A step by step guide with Node.js and Socket.IO</h4><p>In many aspects, smartphones are superior to their desktop counterparts. One killer feature of smartphones are their cameras whose image quality is so much better compared to integrated webcams of a desktop computer.</p><p>On the other hand, desktop computers are often more suited for work that requires large screen real estate and for working with files across different apps.</p><p>While working on <a href="http://www.usetracy.com/"><em>Tracy</em></a>, a web app that converts photos of sketches and drawings to vector graphics, I wanted to combine the benefits of both device types. I needed a simple way to transfer the drawings in front of me to my computer.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*0LQp3zI4AYqarXG-tnMudA.jpeg" /><figcaption>Photo taken with Safari on iOS, synced to Safari on desktop.</figcaption></figure><p>The usual workflow of getting a photo to my computer looks like this: Take a photo, wait for it to upload to the cloud (or get frustrated that it doesn’t work yet again), find the photo in the photos app, drag &amp; drop it into the browser window. Cumbersome. Instead, with WebSockets, we can turn the smartphone into a connected scanner that can transfer photos directly to the desktop web app.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fplayer.vimeo.com%2Fvideo%2F246579946&amp;dntp=1&amp;url=https%3A%2F%2Fvimeo.com%2F246579946&amp;image=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F671581209_1280.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=vimeo" width="1920" height="1080" frameborder="0" scrolling="no"><a href="https://medium.com/media/30b4ecf6d04a1d189b4745687c65a6c2/href">https://medium.com/media/30b4ecf6d04a1d189b4745687c65a6c2/href</a></iframe><p>The following article will explain how I use WebSockets within <em>Tracy</em> to enable cross device communication. I will provide code snippets and a step by step tutorial on how to transfer images from a mobile browser to a desktop browser.</p><h4>What are WebSockets?</h4><p>WebSockets enable developers to push data between devices in real time without the need to store any data. WebSockets require a server that can send and receive data in form of messages, files, images, etc.</p><p>In our case we expect two clients: a desktop website and a mobile website. Both will share data with the server which immediately forwards data to all clients. Similar to a private conversation between you and a friend, we will need a shared channel for our cross device communication.</p><p><em>SocketIO</em> is a JavaScript library that provides a concept of <em>rooms</em> that allows clients to <strong>join</strong> a room and then <strong>emit</strong> or <strong>broadcast</strong> messages to clients in that room. The name of a room can be any string, but in our case it will be a very long random ID that I will explain later.</p><p>For the server implementation, we will need Node.js. If you don’t have it, download and install it from here: <a href="https://nodejs.org/en/">https://nodejs.org/en/</a></p><p>Then:</p><ol><li>Create a new folder</li><li>In that folder, create a file called <strong>package.json</strong></li><li>Copy the following code into <strong>package.json</strong></li></ol><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8a0e5a3087b36aa3a011eddea6ed1175/href">https://medium.com/media/8a0e5a3087b36aa3a011eddea6ed1175/href</a></iframe><p>4. In Terminal, enter:</p><blockquote><em>cd </em>path/to/your/folder</blockquote><p>5. In Terminal, enter</p><blockquote><em>npm install</em></blockquote><p>This will install our Node.js project and all its dependencies. Since we have <a href="https://www.npmjs.com/package/express">Express</a> and <a href="https://www.npmjs.com/package/socket.io">SocketIO</a> already defined in our <strong>package.json</strong>, both packages will automatically be installed.</p><h4>Server Code</h4><p>Now, we will need to open and edit the <strong>index.js </strong>file. There we will add a few lines of code to setup an Express Server that will listen and react to messages coming through the WebSocket.</p><p>In your project folder, create a file called <strong>index.js </strong>and paste the following JavaScript code:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6dc6dcc56fc07bb4762f14c5a3f4b54e/href">https://medium.com/media/6dc6dcc56fc07bb4762f14c5a3f4b54e/href</a></iframe><p>After importing required packages, the server will be started and it will serve a file called <strong>index.html </strong>that doesn’t exist yet. Because we might want to deploy the server on <em>Heroku</em> later, the <strong>port</strong> will be dynamically set by the environment variable, otherwise it defaults to 3000.</p><p>The WebSocket will then listen for clients to connect. Then, after a client requests to join a room, the WebSocket will capture and broadcast events from one client to all other clients in the same room.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*e2xeEgI5YXgfqZEa3UKurQ.png" /></figure><p><strong>Start the server<br></strong>In Terminal, type:</p><blockquote><em>npm start</em></blockquote><p>This will start the server at <a href="http://localhost:3000/"><strong>http://localhost:3000</strong></a><strong>. </strong>Nothing will happen so far. But we’ll soon connect a few clients…</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/894/1*por7Y5__DYGrcKJK0DWHzQ.png" /></figure><h4>Client Code</h4><p>The client example shows a simple website with a file input field and an empty image element. Images selected through the file input will appear in the image element — on all websites.</p><p>In your project folder, create a file called <strong>index.html </strong>and paste the following JavaScript code:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f3e92a75e77c007c3cab765d70778391/href">https://medium.com/media/f3e92a75e77c007c3cab765d70778391/href</a></iframe><p>If you now open <strong>localhost:3000</strong> you should see a website with an input field.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*HcZf52Aj7DHsPA_TQE_usQ.png" /></figure><p>Open the website in two browsers, select an image file in one and you should see the image appear in both browsers.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Nc9z4gIlH5SdztAugiYlTQ.png" /></figure><p>In the head of the page we see a JavaScript reference to <strong>/socket.io/socket.io.js </strong>which is a magic line of code because this JavaScript file doesn’t actually exist in our project.</p><p>But because we are running our own Node.js server with SocketIO installed, it will automatically provide a client version of SocketIO that we need to communicate with the server. Alternatively, we could link to a local or CDN version of <a href="https://cdnjs.com/libraries/socket.io">socket.io.js</a>.</p><p>We can then get an instance of SocketIO that, by default, connects to our local server:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*_pg-XDiE6smR4jrEI-C5Kg.png" /></figure><p>After getting references to DOM elements, we join a room called “test”.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*ivZ6wtfyZl0CrLayXSJ6Cg.png" /></figure><p>A channel name can be any string. Anyone who knows the room name could join it. In order to prevent strangers, you might want to generate very long random room names, such as “5bbad6cf-0e8d-43ce-b7d0-dc6e5726c8fa”.</p><p>This so called “UUID” is almost impossible to guess. In the case of <em>Tracy</em>, the desktop website takes care of generating the room ID. After the website has finished loading, the ID will be generated and the “join” event will be sent to the WebSocket.</p><p><em>Tracy</em> then generates a QR code containing the room ID, so that other clients can join the same room. Such UUIDs can be generated using this package: <a href="https://www.npmjs.com/package/uuid4">https://www.npmjs.com/package/uuid4</a></p><p>In our example, all clients join the same, hard-coded room called “test” so there is no need to share the name of the room between clients.</p><p>After all this, the code takes care of reacting to changes of the file input, reading the file and emitting an event to the WebSocket with the actual image data.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*mKjs1K_dXw8fJ3BrMAzaOg.png" /></figure><p>And finally we’re also setting up a listener to receive image events that will then set the image’s src attribute.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*dhpy_5lWYVXJJauDxW8H9w.png" /></figure><p>In a real app, you might want to do more things such as detecting when a client connects or disconnects. Tracy also sends events when the image transfer starts and finishes so that the app can show a loading indicator.</p><h4><strong>Deploy</strong></h4><p>So far, the server and WebSocket run on our local machine. In order to make the project accessible at any time, we need to deploy it. If you don’t know how to host Node.js apps yourself, you can do this by using Heroku and Github.</p><ol><li>Create a <a href="https://github.com/">Github</a> account and push the code to a repository</li><li>Create a <a href="https://heroku.com/">Heroku</a> account</li><li>Create a new app on Heroku</li><li>In the deploy tab, set up <a href="https://devcenter.heroku.com/articles/github-integration">automatic deployments from Github</a></li><li>Make sure you have the Node.js Buildpack enabled in your app’s settings</li></ol><p>With this integration, every time our code changes on Github, Heroku will deploy a new version. We can then also use the public URL of our app in other client apps using WebSockets. We simply need to tell SocketIO the address of our server.</p><blockquote>var socket = io(<a href="https://tracy-sync.herokuapp.com/">https://your-app.herokuapp.com</a>);</blockquote><p>This will allow you to create apps on your local machine and use the Heroku server for communication only.</p><p>That’s it. It took me a while to learn about WebSockets, Socket.IO and figure out how all the pieces need to be connected. After I figured it out, I was quite happy how little code is required and how powerful the concept is.</p><p>❤️ WebSockets</p><h4>A note on WebRTC</h4><p>If you were wondering why we’d need a server at all… good point! Since we only want to send images between two clients, we don’t need a server. With improving support of <a href="http://w3c.github.io/webrtc-pc/">WebRTC</a> (Web Real Time Communication), we will soon be able to reliably establish direct connections between browsers. Unfortunately, WebRTC still requires a server to authenticate and establish connections. So while in theory WebRTC would be a better fit for sharing data between browsers, the setup is not simpler than using WebSockets which have far better browser support.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f9c48f669c8" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The Anatomy of a Thousand Typefaces]]></title>
            <link>https://medium.com/@getflourish/the-anatomy-of-a-thousand-typefaces-f7b9088eed1?source=rss-303939833494------2</link>
            <guid isPermaLink="false">https://medium.com/p/f7b9088eed1</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[fonts]]></category>
            <category><![CDATA[design-tools]]></category>
            <category><![CDATA[design]]></category>
            <category><![CDATA[typography]]></category>
            <dc:creator><![CDATA[Florian Schulz]]></dc:creator>
            <pubDate>Sun, 22 Oct 2017 12:37:29 GMT</pubDate>
            <atom:updated>2020-06-15T08:30:20.224Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*JX-X4MLx8TS70UBYBVj3iw.png" /></figure><h4>An attempt to build a font database with opentype.js</h4><p>Even years after <em>Avatar’s</em> release, there’s one thing Ryan Gosling just can’t get over: the choice of the movie’s logo font “Papyrus”. In the parody produced by <em>Saturday Night Live,</em> the designer of the logo opens the font menu, browses the fonts one by one, and randomly decides to go with “Papyrus”.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FjVhlJNJopOQ%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DjVhlJNJopOQ&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FjVhlJNJopOQ%2Fhqdefault.jpg&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/b70d841c51ff923fce247dc5f83204ab/href">https://medium.com/media/b70d841c51ff923fce247dc5f83204ab/href</a></iframe><p>The seemingly mindless choice of a font is a general problem with font menus: there are either <strong>too few</strong> or <strong>too many</strong> options.</p><p>On one hand, a limitation to system fonts, as seen in the video, can lead to a bad choice because there simply isn’t something better installed.</p><p>On the other hand, web font libraries with hundreds or thousands of fonts can be quite overwhelming and lead to a paradox of choice.</p><h4>Dinner for none: The font menu’s bitter taste</h4><p>The average font menu presents a list of available fonts, sorted by name, but completely unrelated otherwise: A typeface designed for bold headlines is followed by one designed for small user interfaces and then a fancy script typeface made for wedding invitations shows up. Now you either get trapped in a time consuming process of scrolling through the whole list from start to end or you simply decide to pick the first best match from the upper part of the list and call it a day.</p><p>This is obviously not an interface made for systematic exploration — but infinite surprises. While I like to be surprised, I also like to influence my odds.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*y78uKsCrRGRxGOK4neNajg.png" /><figcaption>The font menu in “Papyrus” by Saturday Night Life. Limited choice, various styles, but not necessarily the best possible typefaces.</figcaption></figure><h4>A systematic approach to finding typefaces</h4><p>There are various ways to limit the options. Before I dive into parsing font files, glyphs and metadata tables, let’s first have a look at classification, curated lists and then anatomy.</p><h4><strong>1. Classification</strong></h4><p>Early in design school I’ve learned about the history of writing and practiced calligraphy to understand how writing evolved and how tools had an immediate impact on the design of type faces.</p><p>This lead to sophisticated systems for classifying fonts based on their appearance throughout history. The simplest classifications are <em>serif, sans-serif, monospaced, script </em>and <em>display </em>typefaces<em>. </em>We can usually find those classes in form of filters on any font website:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/860/1*QG5YQPUD3GOyWCS98OREZw.png" /><figcaption>Classification filter interfaces. Top left: Fontshop. Right: MyFonts. Bottom left: Google Fonts. Bottom: TypeKit.</figcaption></figure><p>Those simple filters might still give us too many options. That’s when more specific terms such as <em>transitional serif, humanist serif </em>or <em>blackletter </em>can be introduced to differentiate typefaces of the class <em>serif</em>.</p><p>Sometimes those subcategories are available as tags. But sometimes they just don’t exist in such detail. Maybe there are too many categories? Maybe users don’t understand all those options? Maybe there is just no complete and consistent data available?</p><h4><strong>2. Curated Lists</strong></h4><p>Another way to put order into the chaos is to rely on the knowledge of others: Human-curated font lists. We can find those for example on <a href="https://www.fontshop.com/fontlists">Fontshop</a>. There you can find collections based around a decade in history such as “<em>1930</em>”, based on similarity such as “<em>Helvetica Alternatives</em>” or application specific lists like “<em>Branding</em>” or “<em>Newspapers</em>”.</p><p>Similar lists can be found on <a href="https://typekit.com/lists">Typekit</a>, <a href="https://www.typewolf.com/">TypeWolf</a> or <a href="https://fontsinuse.com/">FontsInUse</a>. I think those lists are great and I encourage everyone to start making their own lists with fonts you have already worked with or seen in application. It will pay off in the future to have those references.</p><h4>3. Anatomy</h4><p>The most complex way to look at typefaces is to focus on their design details and to try to understand what makes a typeface good or special. Fortunately, there are books on type design, typefaces and typography. They can teach us how to make typefaces, how to choose them and how to use them.</p><p>One of those books is “<a href="http://typeanatomy.com/">The Anatomy of Type</a>” by Stephen Coles. A few years after design school, this book was a refresher that reveals details about 100 well established typefaces. Stephen Coles uses terms such as <em>x-height, width, weight, ball terminals, serif style</em> and others to describe the quality of typefaces.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-rjUJV3PhdOpf2M4QZnb8A.png" /><figcaption>“The Anatomy of Type“ — A Graphic Guide to 100 Typefaces by Stephen Coles. A great book if you want to learn about the history and design details of popular typefaces.</figcaption></figure><p>After looking at those 100 typefaces I thought: what about the rest? What about the fonts on my computer? And the ones on the web? What are their xheight, width, weight and contrast? How can I find out?</p><h4><strong>Inside a font file: Lack of meta data</strong></h4><p>Before I started coding, I was hoping that I could find out about the properties of a font in an easy way. In theory, every font file comes with a variety of metadata tables that contain information about name, author, language and visual characteristics of the typeface. <em>Width</em>, <em>weight </em>and<em> </em><a href="https://www.microsoft.com/typography/otspec/ibmfc.htm"><em>font family class</em></a> are the obvious ones. But also information about <em>xheight</em>, <em>cap</em> <em>height</em>, <em>average char width</em>, <em>ascenders</em> and <em>descenders</em> could be found. Another set of metadata called <a href="http://monotype.de/services/pan2"><em>Panose</em></a> describes even more properties such as <em>serif style</em>, <em>proportion</em>, <em>contrast</em> and many more. Using font design apps such as <a href="https://glyphsapp.com/"><em>Glyphs</em></a>, anyone can inspect fonts to view this information:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*WKbuXStJ2TIp9YQ8h24nPw.png" /><figcaption>A screenshot of the “Font Info Panel” of the font design app “Glyphs”. It shows basic information about family name, designer, url, version, date. User definied settings show the Unicode Range and Panose information. The 10-digit code describes many characteristics, but this information is not always available as it has to be defined and measured by the designer or producer of the font file. On the right screenshot one can see metrics such as ascender, descender, x-height, and italic angle.</figcaption></figure><p>But the availability of this information depends on the work that has been put into making the font. While some fonts provide a lot of information, this isn’t always the case, especially not for free or open source fonts such as the ones from Google Fonts. But even if information is provided, it’s not necessarily consistent or complete enough to make comparisons based on it.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*es8dzWbLBeeWMq7MeVDFgA.jpeg" /><figcaption>Comparison of Panose information available for Roboto and Fira Sans, both available on Google Fonts. While Fira Sans provides a lot, Roboto doesn’t. This metadata can obviously not be used to compare fonts…</figcaption></figure><h4>DIY: Parsing fonts with opentype.js</h4><p>So in order to classify and compare typefaces myself, I had to take a close look at font files and find automatic ways to extract information. Fonts are available in a variety of file formats, but eventually they are almost always available as TTF (TrueType Fonts).</p><p>Other formats are OTF (OpenType) that includes information for additional features such as ligatures or WOFF (Web Open Font Format) that can compress the font and store additional meta data.</p><p>These days, thanks to Frederik De Bleser’s <a href="https://opentype.js.org/"><em>opentype.js</em></a>, we can inspect font files using JavaScript in a web browser. <em>Opentype.js</em> gives us access to vector information of all the glyphs included in a font file and it also provides access to key metrics and metadata tables.</p><h3>A database of characteristics</h3><p>In the following section I will describe how I measured <em>contrast, x-height, width and weight </em>of all fonts provided in the Google Fonts Library. The same methods could be applied to other font libraries such as Typekit or fonts from your computer.</p><h4>Stroke contrast</h4><p>The contrast describes the ratio of thin to thick strokes. There are typefaces with little stroke contrast, e.g. slab serifs or many sans serif typefaces designed for user interfaces, e.g. <em>Roboto </em>or <em>San Francisco</em>. There are others with a lot of contrast, such as <em>Bodoni</em> or <em>Didot</em>. To measure the contrast, we can trace the outlines of an “o<em>”</em> and look for the smallest and largest distances between inner and outer shape.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1004/1*qK7j4w_zyY_czBtDZpsobQ.png" /><figcaption>The contrast of a typeface may be measured at the thickest and thinnest part of an “o”.</figcaption></figure><p>It’s a simple and comparable letter shape that almost always consists of two paths. It’s a good candidate for estimating the contrast of a typeface. (Side note: While seemingly simple, the shape of an “o” is actually quite hard to draw well, because the stroke needs to smoothly grow and shrink between thin and thick.)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/661/1*Mc-L8SSYLCFrrew-ivzi7A.gif" /></figure><p><em>opentype.js</em> provides convenient ways to get path data to draw characters to a SVG element. I actually draw inner and outer paths separately. Then I used an <a href="https://bl.ocks.org/mbostock/8027637">algorithm</a> that travels along each path and measures the distance at each point. We can then calculate the ratio between the longest and shortest distance and voila — we have a comparable <em>contrast</em> measurement.</p><h4>x-height</h4><p>The x-height is an important characteristic that can be an indicator for legibility and perceived size of a font. It is usually measured at the top of a lowercase <em>x</em>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1004/1*bQiWjA4_oc2gCRchwwEWog.png" /><figcaption>The x-height can be measured from the glyph information that opentype.js provides.</figcaption></figure><p><em>opentype.js</em> provides us with the needed measurements, namely <em>yMax </em>for any glyph.</p><p>In addition to the absolute measurement, it might be useful to also compare the x-height to the height of the ascenders. Thus, we can get percentage values such as “the x-height is 60% of the uppercase letters”.</p><p>To make the values comparable (some fonts use 1000 unitsPerEm, others 2048 unitsPerEm), it is necessary to normalize the values and map them to a range of 0–1.</p><h4><strong>Width / Proportion</strong></h4><p>With this value I try to grasp how narrow or wide a font is. Is it rather condensed or extended? One idea I had was to measure the width of an “M”. But to make those comparable, one would need to put those into context of the overall size or the x-height. Some typefaces also might have very special “M” glyphs that don’t represent the rest of the typeface.</p><p>Another idea is to calculate the average glyph width using a sample word like “Hamburgefontsiv”. While this works quite well, it also would need some normalization in respect to the overall design and height of the typeface.</p><p>Another approach is to look at the proportion of an “o”. This gives suprisingly good values for comparing the widths of fonts.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1004/1*5H0_x-KFMb4UdRgdxBGJbw.png" /></figure><h4>Weight</h4><p>To measure the weight, I render the lowercase „o“ character to a HTML canvas element, fill it black and paint the background white. I then measure the ratio between black and white pixels. A script or hairline font will show very little values, while a very heavy blocky font will show high values. This gave me okayish results, but I want to improve this by measuring actual stems of glyphs in the future.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1004/1*Dn6GG3vjYt-NlkSnLdPDng.png" /></figure><h4>Spacing</h4><p>When all glyphs of a typeface have the same width, they are called monospaced. Important here is, that we can’t necessarily look a the glyphs themselves to determine the width. Even in a monospaced font, a dot character takes less visible space than a “m”. Thus, we need to take into account the <em>advanceWidth</em> property that describes the invisible width around a glyph. Here we can find out that Google Fonts uses <em>monospaced</em> as a style classification, but not to indicate the technical property. Fonts such as <a href="https://fonts.google.com/specimen/Lekton"><em>Lekton</em></a><em> or </em><a href="https://fonts.google.com/specimen/Libre+Barcode+39+Extended"><em>Libre Barcode</em></a><em> </em>are<em> </em>not listed as <em>monospaced,</em> but technically they are.</p><h4><strong>Similarity</strong></h4><p>Once we have a table of values, we can normalize those and then compute distances to see how similar fonts are. I implemented a very basic version of it that isn’t terrible, but could be better with higher accuracy of the data. Also, we might perceive similarity different than an algorithm that treats every characteristic equally. In that case, we might need to weigh some properties more than others.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*z_rEAMIty0bt-lImtPOgMQ.gif" /><figcaption>The font parser analyses each font, draws hidden SVGs and canvas elements for measurements and saves the data to a JSON file.</figcaption></figure><h3>Demo</h3><p>I’ve built an interface to make the database accessible. Fonts can be viewed in a grid of varying size to get an overview over all fonts or to take a look at details of a few fonts.</p><p>Fonts can be <strong>sorted</strong> by weight, x-height, contrast, width, name and number of styles. Depending on the sorting criteria, adequate glyphs are shown.</p><p><strong>Area charts</strong> show the distribution of values and can be used to filter out certain values. Each font has a <strong>detail view</strong> with a few samples, glyphs, metrics, <em>Panose</em> information and similar fonts.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*1nX9AFEcLzrVCjCwZdCXUg.png" /><figcaption>Screenshot of the project’s website</figcaption></figure><p><strong>Explore the dataset<br></strong><a href="https://useratio.com/the-anatomy-of-a-thousand-typefaces">https://useratio.com/the-anatomy-of-a-thousand-typefaces</a><strong><br></strong><br><em>For some reason some fonts fail to load in Safari, so I recommend to use Chrome.</em></p><p><strong>Screencast<br></strong><a href="https://vimeo.com/239318934">https://vimeo.com/239318934</a></p><h3>Findings</h3><p>The dataset invites one to explore and find similarities and irregularities. Setting <em>low contrast</em> and <em>serif</em> will return all the <em>slab serif</em> fonts. Low <em>x-height</em> will give us mostly handwritten or script fonts. Very high values often indicate <em>all caps</em> typefaces.</p><p><strong>Misfits</strong><br>Selecting the lower or upper ends of the spectrum will often return very weird designs. They mostly fall into the category <em>display</em>.</p><p><strong>Ugly differences<br></strong>The grid overview reveals the awful differences of baselines and alignments. Some fonts are radically off the grid. And even with subtle differences, it becomes clear that a simple 1-to-1 font substitution is almost impossible — with the exception of some popular fonts that all seem to share a similar skeleton.</p><p><strong>Average is good<br></strong>It’s interesting to see that commonly used fonts we consider to be good, all fall into a similar subset. By adjusting the filters, I can cut down the list to less than half and all the popular fonts will still be there. Selecting the average ranges is a simple way to filter out the misfits and extremes.</p><p><strong>Forked Fonts</strong><br>We can also find fonts that look exactly the same as others but with different names. Some of those are forks that extend the character set to support additional languages, e.g. <em>Alegreya &amp; Sahitya.</em></p><p><strong>Number of styles<br></strong>Above all, the number of styles a font has is a good indicator for its quality — at least as long as designers still need to make a lot of effort to design various weights and styles. <a href="https://medium.com/@tiro/https-medium-com-tiro-introducing-opentype-variable-fonts-12ba6cd2369">Variable fonts</a> are on the horizon and infinite customization may be the future. But until then, it’s good advice to work with font families that have multiple styles. Thus, sorting the collection by number of styles is a fast way to get an overview of the best fonts available.</p><h3>Summary</h3><p>This is a complex way of looking at font exploration. Ultimately, the quality of results depends on the quality of the fonts and the data around them. Only browsing Google Fonts is very limiting as their overall quality isn’t known to be the best in class. I’ve already started to run analysis on the Typekit library and ultimately met new challenges of user interface performance when previewing so many fonts. Such an undertaking requires proper caching and preloading strategies. But I don’t have to go that far just yet.</p><p>With no AI involved, I now have a good understanding of what’s inside font files and what’s missing. The more and more I got into this, I realized how massive the field of font technology is and that I’m only getting into something that’s been done for decades already.</p><h4>Possibilities</h4><p>With such a dataset, one could do more things:</p><ul><li>find fallback fonts with a similar width or style</li><li>automatically adjust font sizes and line heights based on x-height</li><li>find font combinations based on similarity or difference</li><li>build a custom font menu for Avatar’s poster designer</li><li>…</li></ul><p><strong>Try the app</strong><br><a href="https://useratio.com/the-anatomy-of-a-thousand-typefaces/app/">https://useratio.com/the-anatomy-of-a-thousand-typefaces</a></p><p><strong>Watch screencast</strong><br><a href="https://vimeo.com/239318934">https://vimeo.com/239318934</a></p><p>Before I publish the raw dataset I want to improve the analysis and try to add more characteristics. If you have any ideas for improvement, don’t hesitate to leave a comment. Thanks for reading!</p><h4><strong>Further reading</strong></h4><p><a href="http://monotype.de/services/pan2"><strong>Panose Classification Metrics Guide</strong></a><br>The guide from 1991 describes in detail how to measure individual glyphs to derive comparable metrics. Unfortunately those measurements need to be taken by hand and can be quite time-consuming.</p><p><a href="http://www.jon.gold/2016/05/robot-design-school/"><strong>Taking The Robots To Design School, Part 1 by Jon Gold</strong></a><br>Already in May 2016, <a href="https://medium.com/u/5056df9f86a9">Jon Gold</a> wrote about his approach to analysing fonts in depth, covering topics such as rule based design, artificial intelligence and the relevance of such datasets for design tools.</p><p><a href="https://github.com/googlefonts/tools"><strong>Google Fonts Tools</strong></a><strong><br></strong>A set of open souce tools that are used to analyse fonts for use on the Google Fonts website. You can find similar algorithms there, but also other ones that for example determin the italic angle of a font.</p><p><a href="https://github.com/googlefonts/fontbakery"><strong>Font Bakery</strong></a><strong><br></strong>Font bakery is a set of Python tools that runs checks on TrueType files, and Google Fonts related metadata files.</p><h3>Appendix</h3><p><strong>Q: Why didn’t you use data from web font services?<br></strong>A: Services that provide fonts such as Typekit, Google Fonts, Fontstand, Fontshop, MyFonts, etc. all provide their own set of filters with more or less fine control. The APIs of those services also differ in the amount of information that is available for each font. Usually the category is provided, but other information is either left out or not compatible between the services.</p><p>The following example shows, that all we get from <a href="https://developers.google.com/fonts/docs/developer_api">Google Fonts Web API</a> for <em>Roboto</em> is its category <em>sans-serif</em>, variants and subsets. <a href="https://gist.github.com/getflourish/d79836b0bebb6b44f76389b623fd7dc1">https://gist.github.com/getflourish/d79836b0bebb6b44f76389b623fd7dc1</a></p><p>The <a href="https://typekit.com/docs/api/font_library">Typekit API</a> provides more information about width, x-height, weight, classification, contrast, capitals and a recommendation.<br><a href="https://gist.github.com/getflourish/8c7c9ab4ddcf422cbb77866b5cf61575">https://gist.github.com/getflourish/8c7c9ab4ddcf422cbb77866b5cf61575</a></p><p>As you can see, in the example API result, the information about a font is provider-specific. In order to be more flexible and independent I started to do my own analysis.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f7b9088eed1" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Essentials of interactive prototypes with VueJS in less than 5 Minutes]]></title>
            <link>https://medium.com/@getflourish/essentials-of-interactive-prototypes-with-vuejs-in-less-than-5-minutes-8b6f6f0ed5f5?source=rss-303939833494------2</link>
            <guid isPermaLink="false">https://medium.com/p/8b6f6f0ed5f5</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[vuejs]]></category>
            <dc:creator><![CDATA[Florian Schulz]]></dc:creator>
            <pubDate>Fri, 05 May 2017 10:59:31 GMT</pubDate>
            <atom:updated>2017-05-05T12:47:19.723Z</atom:updated>
            <content:encoded><![CDATA[<p>I recorded a short, <a href="https://youtu.be/c-wtw5uPnJI">screencast</a> to show the core principles of <a href="https://vuejs.org/">VueJS</a> that make it a powerful prototyping tool that requires no setup.</p><p><strong>What’s included:</strong></p><ul><li>Dynamically render data to HTML using the simple <strong>template syntax</strong></li><li>Use <strong>v-model</strong> to keep user input and data in sync</li><li>Using simple functions, like “length” in your markup</li><li>Rendering lists using <strong>v-for</strong> (characters of a string, Array, Object, …)</li><li>Adding user interaction with <strong>v-on </strong>(click, keyup, …) to call a method</li><li>Using <strong>v-bind:class</strong> to conditionally apply classes to an element</li></ul><p><strong>What’s not included:</strong></p><ul><li>entertaining music or sexy visuals</li><li>Flux, SSR, Routing, Babel, Webpack, Functional Programming, Immutables, CSS-in-JS, … this isn’t necessary to create an interactive throw-away protoype. Save all of that for later and then use <a href="https://github.com/vuejs/vue-cli">vue-cli</a> or <a href="https://nuxtjs.org/">nuxt-js</a> when you want to go develop something for real 👾</li></ul><p>With those concepts, you can already achieve a lot without writing a lot of JavaScript.</p><p>You can learn more by reading the great documentation with many more examples at <a href="https://vuejs.org/">https://vuejs.org/</a></p><p>Enjoy and share this with your designer friends who are eager to add HTML prototypes to their toolbox but are afraid it would take them too long to learn 😎</p><h4>The video</h4><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2Fc-wtw5uPnJI%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3Dc-wtw5uPnJI&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2Fc-wtw5uPnJI%2Fhqdefault.jpg&amp;key=d04bfffea46d4aeda930ec88cc64b87c&amp;type=text%2Fhtml&amp;schema=youtube" width="640" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/a157f83f56834d921cba24b213bab9b7/href">https://medium.com/media/a157f83f56834d921cba24b213bab9b7/href</a></iframe><p><strong>Note for the haters of template syntax:</strong> If prototyping speed is not your main goal and you rather want to develop a larger, scalable application, VueJS also lets you write components using more verbose code and render functions.</p><p>You can find the CodePen here: <a href="https://codepen.io/getflourish/pen/JNrMEe">https://codepen.io/getflourish/pen/JNrMEe</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8b6f6f0ed5f5" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Designing with intent]]></title>
            <link>https://medium.com/@getflourish/designing-with-intent-be6664b10ac?source=rss-303939833494------2</link>
            <guid isPermaLink="false">https://medium.com/p/be6664b10ac</guid>
            <category><![CDATA[design-systems]]></category>
            <category><![CDATA[css]]></category>
            <category><![CDATA[interaction-design]]></category>
            <category><![CDATA[typography]]></category>
            <category><![CDATA[design-tools]]></category>
            <dc:creator><![CDATA[Florian Schulz]]></dc:creator>
            <pubDate>Sun, 06 Nov 2016 14:30:57 GMT</pubDate>
            <atom:updated>2017-10-24T17:53:01.142Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*j0qQQWQCvQLRsr0dpiBe5A.png" /><figcaption>Visualisation of mouse movements when I was working in a design tool back in 2009. What’s the intent behind each click, drag or nudge? <a href="https://www.flickr.com/photos/fl0urish/4155725071/in/photostream/">https://www.flickr.com/photos/fl0urish/4155725071/in/photostream/</a></figcaption></figure><p>In 2016, I’ve seen an ever increasing number of style guides and articles on design systems on the web. More and more web and interface designers started to document their color palettes, text styles and component libraries that help them with consistency and scalability.</p><p>While a lot of effort goes into documentation and implementation of design systems, I think we actually need some tools that help us <strong>create</strong> such systems in the first place.</p><p>Personally, I’m looking for better ways to design<strong> relationships</strong> and have means to express and communicate my design <strong>intentions</strong>.</p><p>I feel that the next generation of design tools would benefit from a solid foundation that promotes a systematic approach to screen design. These tools will likely need to work different than we’re used to, but it might also make us more productive and reduce the time for house-keeping.</p><h3>Building my own tools</h3><p>To illustrate my point, I developed a simple tool that helps me design a responsive typographic scale. It’s a visual interface for creating a modular scale with fluid type.</p><p>While <a href="https://github.com/modularscale/modularscale-sass">Modular Scale for Sass</a> and <a href="https://madebymike.com.au/writing/precise-control-responsive-typography/">CSS calc()</a> are simple to implement technically, I struggled to find the right values for all the parameters that are involved.</p><p>I felt tired of guessing and typing values, reloading the page to see changes, resizing the browser to see how it behaves on various screen sizes, etc. I felt rather trapped in a mechanical process, than being empowered by the system. I thought that I needed a simple interface to better understand the dependencies and behaviors of the different parameters. I had to see this in real-time.</p><h3>How it works</h3><h4>Parameters, not values</h4><p>There are two sets of controls on the left that I can use to manipulate the <strong>container width</strong>,<strong> base font size</strong> and <strong>contrast</strong> of the modular scale at each extreme. This is the core playground where I can tweak as long as I want and see how the system behaves.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/681/1*5uNStlInjCzyqctQ0Pr2zQ.gif" /><figcaption>Scrubbers make it easy to explore the full range of possibilities with less effort than input fields or keyboard shortcuts</figcaption></figure><p>It’s important to note, that sizes and contrast depend on the overall design and white space. While big contrast can look great on a big screen, the same contrast ratio will look off on a small mobile device screen.</p><p>This means, that simply making <em>everything </em>smaller on mobile (e.g. decreasing the base font size of the HTML element) isn’t enough. Titles will be too big compared to the available screen estate. We can improve that by using <strong>less contrast</strong> for the modular scale on our <strong>minimum</strong> end.</p><h4>Interpolation</h4><p>The tool shows <strong>minimum &amp; maximum </strong>views (“masters”) of a sample article design with a few headings and body copy in different sizes. All font sizes in between are interpolated. This is the so called <em>fluid type</em>.</p><p>Instead of thinking about arbitrary breakpoints and fine tuning each font size for each breakpoint, would it be enough to just think about the <strong>extremes </strong>and how they play together? How does it feel to design minimum and maximum in <strong>parallel?</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*WOZt8WWRrMWU10dAUzg1ZQ.png" /></figure><p>Designing with those “<a href="https://www.glyphsapp.com/tutorials/multiple-masters-part-1-setting-up-masters">multiple masters</a>” is common in the making of typefaces. By designing two extreme weights (e.g. <em>black and thin</em>), you are able to interpolate in between and generate as many weights as you want (e.g. <em>bold, regular, light</em>).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/775/1*vuerfUfXqqq_QsyH3S_8Bw.png" /><figcaption>Multiple weights of the lowercase letter “k” overlapping. “TheSerif” designed by Luc(as) de Groot.</figcaption></figure><p>Usually, the visual quality of interpolations is not guaranteed to be perfect and manual adjustments by eye are required.</p><p>Such a combination of algorithmic automation and human fine tuning seems to be a good approach to me. <strong>Computers assisting with design, not taking over.</strong></p><p>I believe that interpolation can be a useful method to deal with other complexities such as designing for many different <em>devices, screens, light conditions, and other contexts</em> that we cannot fully control or anticipate.</p><p>For more information on that topic of interpolation, I recommend reading “<a href="http://www.lucasfonts.com/about/interpolation-theory/">Interpolation Theory</a>” from 1987 by Luc(as) de Groot.</p><h4>Snappy previews</h4><p>I can drag handles on each preview to temporarily resize them and see how the design responds when it gets wider or narrower. Once the mouse is released, the previews snap back to their initial size.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/673/1*no3Ap8qxMrFdfzYEtM2LRw.gif" /></figure><h4>Steps</h4><p>Each text layer shows a number on hover. This is the step used for the modular scale. I can <strong>increase / decrease</strong> the steps to make changes to the visual hierarchy while staying within the system.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5LBfUDDS5k_oFN6_Gay5Jg.gif" /></figure><h4>Limitations</h4><p>The tool is very limited and addresses only a few aspects of web typography. When we look at typography theory, there are a lot more rules and relationships that we could encode. To be more precise, we would also need to read the font metrics to derive the x-height or other measures as a base instead of using the font-size. Right now, two different fonts using the same parameters would lead to very different results. This is because the actual perceived size of a font is not directly related to the font size.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*4EAXv_ConnbOBaQ9bCyNqA.png" /><figcaption>Two different fonts with technically same size and line height often result in different perceived size, number of lines, and paragraph contrast. Here: “Avenir Next” on the left and “Alegreya” on the right.</figcaption></figure><p>In reality, we would also need to be able to bind our system to HTML containers instead of relying on the width of the page. Currently, this is only possible with JavaScript and using libraries such as <a href="http://elementqueries.com/">EQCSS</a>. There is a lot more that needs to be done to make such a system more generic and bullet proof for various use cases.</p><p><strong>So nope, you can’t:</strong></p><ul><li>Choose fonts</li><li>Change spacings</li><li>…</li></ul><h3>Working with systems and limitations</h3><p>Setting up a modular scale only in code is the wrong solution. Design tools and code environments need to be able to share the same information about the underlying systems. A <strong>middle man</strong> that understands various tools and formats might be needed. <a href="https://github.com/salesforce-ux/theo">Theo</a> by Salesforce is an interesting approach to that.</p><p>Think of it as a design police (or a <em>design linter</em>) that ensures that you stay within the system or whatever rules you agreed on as a team. Instead of freely choosing from a continuous range of font sizes, your tools would automatically snap when you resize. Similar mechanisms are imaginable when working with color, spaces, and other properties.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/828/1*nCJ-nU9y4U1ltrGeW7oqZQ.gif" /><figcaption>Prototype of a design tool that snaps font sizes to a defined range of sizes</figcaption></figure><p>If that sounds interesting from a CSS point of view, you should check out “<a href="https://github.com/meodai/dialog-size">Dialog Size</a>” by my co-worker <a href="https://github.com/meodai">David Aerne</a>.</p><h4>The concept of contrast</h4><p>Using the contrast scrubber feels very powerful to me. Instead of tweaking multiple individual font sizes, I control one single parameter to influence the whole system. Although I usually read about “scale” or “factor” in articles about modular scale, I find the term “contrast” more suitable. While scrubbing, I directly influence the contrast between the body font size and all other sizes. The bigger the value, the bigger the contrast.</p><p>I also believe that <em>contrast</em> is a powerful way of thinking about various design relationships. It doesn’t only apply to a typographic scale, but also to space and color.</p><p>For example, instead of picking a text color that “looks good” and is legible, we could simply define a desired color contrast (e.g. 4.5) and let the design tool figure out the actual color based on the background color of the text.</p><p>That way we have aesthetic control (“high or low contrast”) while also ensuring legibility.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/914/1*awlFGp8nPdKKxjj7haPekw.gif" /></figure><h3>Build your own tools</h3><p>I’ve made this tool as a proof-of-concept. I wanted to get a feeling for what it would be like to control and play with parameters instead of typing code. I also wanted to find out how designing for minimum &amp; maximum at the same time feels and whether that is more useful than only seeing on state at a time.</p><p>All I get from those hacks are usually learnings. It takes a lot more effort to turn those ideas into real tools that work in production. But I still want to encourage anyone to start building your own (small) tools if you can. Help yourself!</p><p>Complaining about a lack of features won’t bring us anywhere soon. That’s also the reason behind the many Sketch plugins I developed. (<a href="https://github.com/getflourish/Sketch-Color-Contrast-Analyser">Color Contrast Analyser</a>, <a href="https://github.com/getflourish/Sketch-Set-Line-Height-Plugin">Line Height</a>, <a href="https://github.com/getflourish/Sketch-Mate">Mate</a>, <a href="https://github.com/getflourish/Sketch-Style-Inventory">Style Inventory</a>, <a href="https://github.com/getflourish/consistency">Consistency</a>, …).</p><p>In my opinion, the fact that <a href="https://medium.com/u/d39f69b23aa2">Sketch</a> has a completely open API that plugin developers can build on, is the most powerful feature. The team behind Sketch basically accepted that they can’t solve every individual’s problem. But they made it incredibly easy to use our creativity to build tools on top of a solid foundation.</p><h3>Try the tool</h3><p>You can try “<a href="http://codepen.io/getflourish/full/vXqewy/">Adaptive Modular Scale</a>” on CodePen. It’s not really intended for real world use and I didn’t test it thoroughly. It’s also pretty obvious that designing the “maximum” state requires a large screen or using the zoom control that I didn’t build 😇</p><h3>Credits</h3><p>I started to work on the tool after reading the article “<a href="https://madebymike.com.au/writing/precise-control-responsive-typography/">Precise control over responsive typography</a>” by <a href="https://medium.com/u/603fc650f7e">Mike Riethmuller</a>. Seeing that fluid type is possible with CSS today made it even more interesting to try it out in more detail. Is it a silver bullet? No. But it is one way to deal with typography on the web.</p><p><a href="http://www.modularscale.com/">Modularscale.com</a> is a tool that previews modular scale as a water fall of text. I think the website has made the concept a lot more popular. Personally, I find the type of visualisation only partially helpful. I like to see the system in context (example article or a real project). A tool by <a href="https://medium.com/u/451a777d0bab">Tim Brown</a> and <a href="https://medium.com/u/a14b7d76c18a">Scott Kellum</a>.</p><p><a href="https://www.gridlover.net/">GridLover</a> is a tool that also helps you establish a modular scale including a vertical rhythm. Essentially a better and more complete version of my experiment, but without the interpolation. I love how <a href="https://medium.com/u/aba81fd9f012">Tuomas Jomppanen</a> and <a href="https://medium.com/u/c42f2b278069">Ville Vanninen</a> integrated scrubbers inside the CSS panel!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=be6664b10ac" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Custom Selections in Sketch App]]></title>
            <link>https://medium.com/ginetta/custom-selections-in-sketch-app-fb802042918e?source=rss-303939833494------2</link>
            <guid isPermaLink="false">https://medium.com/p/fb802042918e</guid>
            <category><![CDATA[design]]></category>
            <category><![CDATA[plugins]]></category>
            <category><![CDATA[sketch]]></category>
            <dc:creator><![CDATA[Florian Schulz]]></dc:creator>
            <pubDate>Mon, 18 Jul 2016 10:06:48 GMT</pubDate>
            <atom:updated>2016-07-19T09:01:12.922Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*V52BphshD3-kGlZ0cA5-dA.png" /></figure><h4>A brief introduction on scripting commands that computers love to do over and over again.</h4><p><strong>This post is an answer to a Sketch feature request by Information Architects that I’ve stumbled upon Twitter:</strong></p><blockquote>@sketchapp Hey, we all use your program here. We would love to have a “Select all below feature” similar to the one in Axure. Cheers! — via @iA</blockquote><p>I want to explain how this is possible by writing a simple plugin, that you can also <a href="https://github.com/getflourish/Select-Below">download</a> on Github.</p><h4>About writing Sketch plugins</h4><p>It’s been almost a year since I’ve started using Sketch in my design process. In the meantime, I’ve developed <a href="https://github.com/getflourish/Sketch-Mate">dozens</a> of plugins that help me and my colleagues in our daily work at <a href="http://ginetta.net/">Ginetta</a>.</p><p>Fortunately, most plugins only require a few lines of JavaScript to select and manipulate layers.</p><blockquote>Every time I find myself repeating something over and over again, it’s time to use the computer for what it’s good for: automating tedious tasks.</blockquote><p>In this article, I briefly want show you how to select layers based on properties. Selections are the core of most plugins and they are actually quite simple to perform.</p><p>If you’ve never developed a Sketch plugin, but also feel the urge to improve the way you work with Sketch, I recommend that you read the<a href="http://bohemiancoding.com/sketch/support/developer/01-introduction/01.html">Sketch Developer Documentation</a>.</p><h4>Selecting layers with NSPredicate</h4><p>The most efficient way to make selections is by using <a href="https://developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/Foundation/Classes/NSPredicate_Class/index.html">NSPredicate</a>. It allows you to write simple queries that can select layers by style, text value, position, size and every other possible property of a layer, artboard, or page.</p><p>For example, the following line of code could be used to select all layers with a <strong>y-position greater than the mouse position:</strong></p><blockquote>var predicate = NSPredicate.predicateWithFormat(“frame.y &gt; %@”, mouseY);</blockquote><p>You could also select all text layers that have <strong>specific text value</strong>. Imagine you found a typo in a headline that appears on multiple artboards. If only you could select all those layers at once…</p><blockquote>var predicate = NSPredicate.predicateWithFormat(“stringValue == %@”, referenceString);</blockquote><p>To turn those selections into working plugins, you need to define a scope that you want to search on. This can be the whole document, a page, an artboard, a layer group or multiples of them.</p><p>The following command would set the scope to all children of the current page (including artboards, layers, shapes, …):</p><blockquote>var scope = doc.currentPage().children();</blockquote><p>Often, I find it more useful to only select layers that are on the same hierarchical level as the selected layer:</p><blockquote>var scope = selection[0].parentGroup().layers().array();</blockquote><h4>Example plugin</h4><p>For demonstration purposes, here is a bare bone example that selects all layers below a selected layer. I also wrote a <a href="https://github.com/getflourish/Select-Below">plugin</a> that uses the mouse position as a reference.</p><p>Imagine that you just removed a section in the middle of your design and now you want to move all layers below the section up to fill the gap.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/604/1*gNKkA0NbxtZYJrFdpKyFTQ.gif" /></figure><p>We need to define the scope of our selection. In this case, we limit the selection to layers on the same layer level as the group that our selection is in.</p><blockquote>var scope = selection[0].parentGroup().layers().array();</blockquote><p>Because we want to get all layers below the current layer, we need to calculate the y-position of the bottom edge of the selected layer. The frame of a layer holds all the relevant position and size properties.</p><blockquote>var frame = selection[0].frame();<br>var bottom = frame.y() + frame.height();</blockquote><p>Now we can set up our NSPredicate filter, that checks each layers’<em>frame.y</em> property and compares it to the previously calculated<em>bottom value.</em></p><blockquote>var predicate = NSPredicate.predicateWithFormat(“frame.y &gt; %@”, bottom);</blockquote><p>Now we need to get an array of matched layers</p><blockquote>var queryResult = scope.filteredArrayUsingPredicate(predicate);</blockquote><p>Finally, we can tell our document to select all those layers</p><blockquote>doc.currentPage().selectLayers(queryResult);</blockquote><p>That’s it. Less than 10 lines of code that are only a shortcut away to make your life easier.</p><p><strong>I recommend that you check out the </strong><a href="https://github.com/getflourish/Select-Below/blob/master/Select%20Below.sketchplugin/Contents/Sketch/script.cocoascript"><strong>source code</strong></a><strong> or </strong><a href="https://github.com/getflourish/Select-Below"><strong>download the plugin</strong></a><strong> (for Sketch 3.3+) on Github.</strong></p><p>To learn more or get inspired, check out my plugins <a href="https://github.com/getflourish/Sketch-Mate">Sketch Mate </a>and<a href="https://github.com/getflourish/Sketch-Style-Inventory">Sketch Style Inventory</a> on Github. I also recommend you to join the <a href="http://sketchplugins.com/">Sketch Developer List</a>.</p><p><a href="http://ginetta.net/"><strong>Ginetta</strong></a> is a digital agency that specializes in user-centered design and development. We create meaningful experiences that are fast, simple and beautiful.</p><p>This post has originally been published at <a href="http://blog.ginetta.net/">blog.ginetta.net</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=fb802042918e" width="1" height="1" alt=""><hr><p><a href="https://medium.com/ginetta/custom-selections-in-sketch-app-fb802042918e">Custom Selections in Sketch App</a> was originally published in <a href="https://medium.com/ginetta">Ginetta</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>