Matthew Roach All articles from matthewroach.me 2020-10-25T00:00:00+00:00 https://matthewroach.me/ Matthew Roach feed@matthewroach.me A modifier modifying a modifier - SUIT CSS 2020-10-25T00:00:00+00:00 https://matthewroach.me/a-modifier-modifying-a-modifier-suit-css/ <p>Now, that is a tongue twister.</p> <p>So, what am I talking about after making you say that tongue twister...</p> <p>Components within <a href="http://suitcss.github.io/">SUIT CSS</a> provide a way to encapsulate CSS to a given component of HTML. As a component has the ability to be a complex item, that's where you can use <code>modifiers</code>, <code>descendants</code> and <code>state</code>. These naming's allow for components to broken up and allow for more meaningful relationships between the CSS and HTML.</p> <p>As per the docs of <a href="https://github.com/suitcss/suit/blob/master/doc/naming-conventions.md#ComponentName--modifierName">SUIT CSS</a>.</p> <blockquote> <p>A component modifier is a class that modifies the presentation of the base component in some form (e.g., for a certain configuration of the component).</p> </blockquote> <p>All this makes sense and is easy to follow based on simple examples. You can use the <code>--modifierName</code> to allow change the presentation of the base component. So in theory you could have a <code>--large</code> modifier that makes the item larger. Either with padding, font or other properties.</p> <p>But let's look at a more realistic example. I am using a <code>button</code> here make it a little easier to follow, and it does provide some good examples.</p> <p>Based on what we know. You use a modifier to modify the base component. Lets say you have a set of designs for buttons that have different visual appearances based on size and types. Lets break down what we are trying to achieve for the button based on the designs.</p> <ol> <li>Standard button (default)</li> <li>Secondary button (secondary) - same as default with a different background color and font colour.</li> <li>Larger standard button (large) - Has different colour, font, spacing, borders.</li> <li>Larger secondary button (large secondary) - Similar to secondary, in it follows the large but with different background and font colours - even different from default/secondary.</li> </ol> <p>Based on the requirements you could think about breaking this up as following using SUIT CSS</p> <ul> <li><code>.Button</code></li> <li><code>.Button--large</code></li> <li><code>.Button--secondary</code></li> </ul> <p>Makes sense. What about the requirement of the different colours. So the secondary and large secondary don't use the same background color.</p> <p>This is where the point of my post comes in. One way to achieve this is for the large secondary modifier to modify the secondary. See the follow example to understand it a little easier</p> <h2>Modifier Solution</h2> <p class="codepen" data-height="265" data-theme-id="light" data-default-tab="css,result" data-user="matthewroach" data-slug-hash="XWKMrEw" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="SUIT CSS - Modifier - Modifier"> <span>See the Pen <a href="https://codepen.io/matthewroach/pen/XWKMrEw"> SUIT CSS - Modifier - Modifier</a> by Matthew Roach (<a href="https://codepen.io/matthewroach">@matthewroach</a>) on <a href="https://codepen.io/">CodePen</a>.</span> </p> <script async="" src="https://static.codepen.io/assets/embed/ei.js"></script> <p>Looking at the Sass, it doesn't appear to be too bad. But look at the styles in developer tools. <code>.Button .Button--large</code> is overwriting all but one CSS property of <code>.Button</code>. This feels like an anti pattern, even though it's not documented in the SUIT CSS docs. Also the need to explicitly set the styles <code>&amp;.Button--secondary </code> inside the <code>.Button--large</code> feels messy and prone to future problems. This also shows that <code>.Button--secondary</code> is never the same in ever case which I would expect from a modifier.</p> <h2>Solution A</h2> <p>One possible solution would be to set a <code>--default</code> modifier for you guess it. The default buttons. This allows the ability to have the <code>--secondary</code> modifiers work a little more as intended. You are not over writing styles unnecessary. But again this still doesn't feel right that the modifiers are inter linked with each other.</p> <p class="codepen" data-height="265" data-theme-id="light" data-default-tab="css,result" data-user="matthewroach" data-slug-hash="PozpNaj" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="SUIT CSS - Default - Modifier"> <span>See the Pen <a href="https://codepen.io/matthewroach/pen/PozpNaj"> SUIT CSS - Default - Modifier</a> by Matthew Roach (<a href="https://codepen.io/matthewroach">@matthewroach</a>) on <a href="https://codepen.io/">CodePen</a>.</span> </p> <script async="" src="https://static.codepen.io/assets/embed/ei.js"></script> <h2>Solution B</h2> <p>Another solution which feels much cleaner. Break the <code>Button</code> into multiple SUIT components. <code>Button</code> and <code>ButtonLarge</code> for the intended purpose and design, this allows to keep them isolated, avoid potential side effects. Keeps the CSS cleaner and consistent. And each modifier is responsible for a limited set of modifications with out needing to rely on other modifiers.</p> <p class="codepen" data-height="265" data-theme-id="light" data-default-tab="css,result" data-user="matthewroach" data-slug-hash="VwjpaBj" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="SUIT CSS - Multiple Components"> <span>See the Pen <a href="https://codepen.io/matthewroach/pen/VwjpaBj"> SUIT CSS - Multiple Components</a> by Matthew Roach (<a href="https://codepen.io/matthewroach">@matthewroach</a>) on <a href="https://codepen.io/">CodePen</a>.</span> </p> <script async="" src="https://static.codepen.io/assets/embed/ei.js"></script> <h2>Conclusion</h2> <p>As you can see, there are many ways to achieve the same outcome. With the documentation not explicitly calling out all possible examples it can sometimes be tricky to work out the SUIT way. Now this isn't anything bad with SUIT or following a methodology.</p> <p>Following a CSS methodology is a very good way to standardise and enforce rules across a team. It doesn't particular matter which methodology you decide to use, so long as it is an agreed approach. Having something in place is a good start, also using something that is well documented and has team buy in.</p> <p>One of the downsides of documentation of such tools and methodologies is they are at a high level. They do not always include good examples of real examples. It's not easy to cover all examples or edge cases. This can leads to issues outlined here. A side affect to this is following a methodology can make reviewing code in a team a little more difficult. Each of the two solutions are viable solutions to the problem. But also the modifier solution presented first is something that can and will come up based on the interpretation of the documentation.</p> <p>If you are working in a team where you have adopted a methodology or framework or something else where you have come up to a cross roads. Or are struggling as a team to interpret the documentation all the same way. You should document the gaps and the approaches you are taking for your needs. If possible raise questions and contribute back.</p> Wordpress to 11ty 2020-10-20T00:00:00+00:00 https://matthewroach.me/wordpress-to-11ty/ <p> I put off my migration from Wordpress over to 11ty far too long as I was put off by the amount of content I would have to migrate. </p> <p> Over time I made my Wordpress site do more than just be a blog. At one point I was using it as a micro blog and syndicating out to twitter. I was also importing my instagram posts. I was trying and to good effect owning all my content. </p> <p> With all this content housed within Wordpress I was put off having to deal with the migration. </p> <p> Then the other weekend I decided I would just migrate the blog posts and nothing else and see what was involved in the migration process. </p> <p> <a href="https://www.11ty.dev/">11ty</a> touts itself as a "simpler static site generator". It's a simple as adding a markdown file to a directory and running the 11ty command to generate a static site, it is <a href="https://www.11ty.dev/docs/resources/#zero-config">zero config</a> by default. Having played with other static site generators it is certainly the simpliest to get up and running. </p> <p> With 11ty being so simple it makes you think, am I missing something. I took some time to understand how best to approach setting up my blog. </p> <p> 11ty has many template languages available out the box. When you run the 11ty command it will process them and create outputted HTML. On top of the template languages 11ty also has front matter. This confused me a little at first. </p> <p> The gist of front matter and template languages are that they co-exist with each other. You use both together, front matter allows you to place some YAML syntax at the top of your source files to provide 11ty with data/config/options. I am using markdown templates for my blog posts, but if you look at one of my posts it doesn't look like a markdown file you may of written or edited before. </p> <pre> &ndash;&ndash;&ndash; title: "Wordpress to 11ty" date: "2020-10-20" permalink: "wordpress-to-11ty/" layout: "layout/post" &ndash;&ndash;&ndash; &lt;p&gt; I put off my migration from Wordpress over to 11ty far too long as I was put off by the amount of content I would have to migrate. &lt;/p&gt; </pre> <p> This is the first part of the markdown file for this blog post. You start of the file with the front matter YAML, using three dashes and end the front matter data with another three dashes. After the second set of dashes you add your content. As I am using markdown files I can either write markdown or straight up plain HTML. </p> <p> Having understoond how front matter and 11ty work together I begun to work on writing a script to migrate my Wordpress blog posts. Wordpress provides an JSON API to access your data. This may not always be enabled for your instance. It's well documented on Wordpress sites/forums on how to enable it and the endpoints available. </p> <p> With the API enabled I was able to hit the following URL - http://matthewroach.me/wp-json/wp/v2/posts?page=1&per_page=10&categories_exclude=33,36,82 to get the latest 10 blog posts. <br> The <code>categories_exclude</code> param is me telling the API to not return posts for the categories, Instagram, Status and Bookshelf. <br> I also used the <code>per_page</code> param to limit to 10 to test creating my markdown files. </p> <p> Getting JSON was the first part, transforming the JSON into markdown files with the necessary front matter data for 11ty was the next step. </p> <p> There is a handy node package <a href="https://www.npmjs.com/package/json-to-frontmatter-markdown">json-to-frontmatter-markdown</a> that only does one thing, transform a JavaScript object to markdown with front matter. </p> <p> By combining the the json to frontmatter markdown module and node's HTTP functionality you can easily make the API request to the Wordpress API and pass the JSON response through the <code>transformAndWriteToFile</code> function to generate a markdown file for each blog post. </p> <p> The full script I used to fetch and create the 11ty markdown files for all my posts is below. </p> <p> I only migrated the main post body, title, date and slug (url). I wasn't concerned with the categories/tags I had previously set up. This makes my import script pretty simple. If you would like to mainain the other items I've not it's pretty simple to do. </p> <p> The script is a node script. I created an <code>index.js</code> file in the root of my 11ty blog and then ran it using <code>node index.js</code>. This processed the files and saved them to <code>src/posts</code> which is configurable by the path option </p> <pre> const http = require('http'); const transformAndWriteToFile = require('json-to-frontmatter-markdown').default; http.get('http://matthewroach.me/wp-json/wp/v2/posts?page=1&per_page=100&categories_exclude=33,36,82', (response) => { let data = ''; // called when a data chunk is received. response.on('data', (chunk) => { data += chunk; }); // called when the complete response is received. response.on('end', () => { let items = JSON.parse(data); items.forEach(post => { const date = post.date.split('T')[0]; // Split data on T to only get YYYY-MM-DD transformAndWriteToFile({ frontmatterMarkdown: { frontmatter: [ { title: post.title.rendered }, { date: date }, { permalink: `${post.slug}/` }, // Must have trailing slash to if you want pretty URLs { layout: "layout/post" } ], body: post.content.rendered }, path: './src/posts', // Location to place the files fileName: `${date}-${post.slug}.md` }); }); }); }).on("error", (error) => { console.log("Error: " + error.message); }); </pre> <h2>Handling images</h2> <p> Moving text is the simple part. When moving images you'll need to down all the images from your Wordpress blog and update the references in the <code>post.content.rendered</code> part of the script. </p> <p> My script does not handle any image updating as I previously set up my Wordpress blog to host images on S3 and be served via cloudfront. This allowed my migration to be much smoother. </p> <p> I did happen to have a couple of posts that some how had images that where being served via the wp-uploads directory. For those posts I downloaded the images from my server and manually uploaded them to the S3 bucket. Making sure to maintian the filenames, this then allowed me to do a find and replace in the markdown files to update the <code>src</code>. </p> <h3>Wordpress API limit</h3> <p> The Wordpress API only allows you to fetch a maximum of 100 posts per request. Rather than writing extra code to loop through and make multiple API requests and collect all the data before processing you can run the script multiple times, and each time I changed the <code>page</code> query string paramenter. I had just over 100 posts so I had to only run the script twice. </p> <p> Running the script more than once will have no negative impact, if there is a file already in the folder it will just overwrite it </p> Accessibility as Standard 2020-10-10T00:00:00+00:00 https://matthewroach.me/accessibility-as-standard/ <p>Most if not all professional industries have standards, rules, regulations and guidelines that <strong>must</strong> be followed. You may be mistaken but this does also apply to the world wide web. Why does it feel like the web industry is able to get away with not following their <a href="https://www.w3.org/standards/">standards</a>, Is it because they are referred to as guidelines? Does that somehow imply they do not have to be adhered to?</p> <p>Why is it that it's not common practice that websites are not always developed to complete standards &mdash; complete standards includes accessibility! Accessibility is generally the most forgotten aspect - Don't take my word for it, just look at the <a href="https://webaim.org/projects/million/">WebAIM Million</a> - and as you can see it is not getting any better.</p> <p>Some not so <a href="http://www.legislation.gov.uk/uksi/2018/952/contents/made">recent updates</a> in the law that makes accessibility a requirement (starting with public sector websites) is a huge step forward, but why did it take so long? Why does law need to be the driving force, and not meeting all <strong>your</strong> users needs. As a professional working in within the web industry you should be aware of the <a href="https://www.w3.org/">W3C</a> and their standards/guidelines. It is a fundamental piece of the puzzle that is web development.</p> <p>If you look at another industry. For example the trades industry. They each have rules and regulations for each trade.</p> <p>Imagine having an electrician doing some work in your house and using the incorrect wiring for a light fixture. How would you ever know? You wouldn't until it was too late, maybe the circuit would short and cause issues, or worst case it causes a fire. </p> <p>Electrician's have to be approved and work to regulations set out by law. You can even verify an electrician by looking at one of the regulators in the industry.</p> <p>That's just a small example of another trade/industry, the effects of them not doing their work to a given standard can have devastating effects. The same drastic effects are not going to affect your website if it's not accessible to all users &mdash; but not having all users able to use your website is a poor acceptance.</p> <p>If you run an online store you could be missing orders without even knowing. With so much choice on the internet to purchase things you are unlikely going to hear about the poor experience or lack of experience a keyboard user or a user of assistive technology had trying to buy from your store. It is much quicker for them to search for the product on another store and make their purchase via a more accessible store.</p> <p>That is highly likely that you just lost a user who could be making regular purchases. Instead they remember the site they had an easier time and experience using and will continue to return.</p> <p>The same can be said for all websites, if you are providing content - such as a news site if the site isn't easily usable with assistive technology users are using they will find the content elsewhere.</p> Buttons must have discernible text 2020-06-13T00:00:00+00:00 https://matthewroach.me/buttons-must-have-discernible-text/ <p>You may of come across the rule &#8220;<a href="https://dequeuniversity.com/rules/axe/3.5/button-name">Buttons must have discernible text</a>&#8221; when running accessibility audits or using automated tools such as axe-core. </p> <p>The rule is a relative simple rule, and in most cases (depending on your site) a small fix. The simplicity of the rule is something you need to account for if you are using automation tools, or running automated audits.</p> <p>By nature of the rule the pass criteria for is very simple &#8211; does a button have a discernible text value. Let&#8217;s take the axe-core information on what would allow for this rule to pass for a button &#8211;</p> <ul><li>Inner text that is discernible to screen reader users.</li><li>Non-empty <code>aria-label</code> attribute.</li><li><code>aria-labelledby</code> pointing to element with text which is discernible to screen reader users (i.e. not <code>display: none;</code> or <code>aria-hidden="true"</code>.</li><li><code>role="presentation"</code> or <code>role="none"</code> (ARIA 1.1) and is not in tab order (<code>tabindex="-1"</code>).</li></ul> <p>Those points are straight forward, using either one of the different techniques ensure the button has discernible text &#8211; Pass!</p> <p>Now lets look at some example code (The SVG isn&#8217;t complete as the path value was removed to keep it short &#8211; the SVG in the example below is of the twitter bird icon/logo)</p> <pre class="wp-block-code"><code> &lt;button title="twitter" type="button" class="shareButton"> &lt;svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"> &lt;path>&lt;/path> &lt;/svg> &lt;/button></code></pre> <p>We have a button that has the twitter icon within it &#8211; so it&#8217;s a icon button that as you may of noticed with the class name it is a share button. A typical scenario for a lot of websites these days, providing a button near the article or page showing the icon of a social network that allows you to quickly share the content.</p> <p>So the example passes all automated tests. Which is good and bad, yes there is the added <code>title</code> attribute to provide the button with a text value. <strong>But</strong> the primary issue here, and that goes for relying on automated tools alone is <strong>context</strong> &#8211; the tools are unable to determine the context of the element and if the text is going to provide any meaning the user.</p> <p>Some possible better values of the <code>title</code> attributes that could be used &#8211;</p> <ul><li>Share on Twitter</li><li>Share current [page/article] to Twitter</li><li>Share [article title] on Twitter</li></ul> <p>The first two would be pretty simple updates to make, the third could be a little more tricky depending on the way the site is built and the share buttons are built &#8211; but it&#8217;s not an unreasonable ask.</p> <p>The updated version of what would still pass all the test but also provide a more meaningful text value to all.</p> <pre class="wp-block-code"><code> &lt;button title="Share Buttons must have discernible text article on Twitter" type="button" class="shareButton"> &lt;svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"> &lt;path>&lt;/path> &lt;/svg> &lt;/button></code></pre> <p>If you have run a lighthouse audit with the accessibility option enable you may of come across the following &#8211;</p> <blockquote class="wp-block-quote"><p>Only a subset of accessibility issues can be automatically detected so manual testing is also encouraged</p></blockquote> <p>This highlights the need for manual testing &#8211; but just because something passed an automated test it doesn&#8217;t mean it&#8217;s correct. It&#8217;s always worth manually testing your entire site and also using real users. Ensuring the passed tests are valid and make sense within the context of your site.</p> Sass &#8211; the irresponsible loops 2020-05-03T00:00:00+00:00 https://matthewroach.me/sass-the-irresponsible-loops/ <p>As Uncle Ben says</p> <blockquote><p>With great power comes great responsibility</p></blockquote> <p>Pre-processors are pretty popular these days for writing CSS, the enhancements they bring to CSS authoring is a great addition even if it&#8217;s just for variables (yes I know of CSS variables). There are also a ton of other features available in such tools.</p> <p>One such great item is the ability to write loops, for those not familiar with loops in programming they provide the ability to write code that repeats the block of code within the loop multiple times based on a set of conditions. That&#8217;s a pretty basic explanation, and loops can provide great power for repeated tasks.</p> <p>With that last point, &#8220;great power for repeated task&#8221; &#8211; With Sass this can also mean extra outputted CSS. Which can lead to increased CSS file size. In the grand scheme of things may not seem to be that big of a deal but this can lead to extra bandwidth being used by end users, less performant websites, etc.</p> <h2>Example with output within a loop</h2> <p>Here we have a two font variables that we are generating helper classes for using a simple loop. Seems simple enough. But when you look at the output. It may simple obvious on what it may be &#8211; we get an output for each loop item.</p> <p><script src="https://gist.github.com/matthewroach/f2796b0291b5c74ffe7565d7a29fa2cc.js"></script></p> <h2>Loop with placeholder and @extend</h2> <p>By utilising a couple more of Sass feature (yes we write more Sass for less CSS) we can update the code to reduce the complied CSS. By using Sass <a href="https://sass-lang.com/documentation/style-rules/placeholder-selectors">placeholder selectors</a> and the <a href="https://sass-lang.com/documentation/at-rules/extend">@extend at-rule</a> we can update the loop to just extend a placeholder. By default the Sass placeholder selector will not output itself, you have to use the @extend at-rule to. For each time you use the @extend inside a selector it reuses the placeholder styles and adds the selector to the list as shown below</p> <p><script src="https://gist.github.com/matthewroach/2bb7b940c6a8fa25e63bab3fc0d1a22a.js"></script></p> <p>With any pre-processors or tool you are using to generate the items you are serving to you end users. <del>You should</del>, You must pay attention to the generated output. Something that may seem inconspicuous could turn out to be doing more than you expected.</p>