<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="/css/feed.xsl" type="text/xsl"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xml:base="https://chrissmith.xyz" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Chris Smith</title>
    <link>https://chrissmith.xyz</link>
    <atom:link href="https://chrissmith.xyz/feed.xml" rel="self" type="application/rss+xml" />
    <description>The personal blog of Chris Smith, front end web developer from the UK</description>
    <language>en</language>
    <item>
      <title>How to move from junior to senior developer</title>
      <link>https://chrissmith.xyz/blog/2026/how-to-move-from-junior-to-senior-developer/</link>
      <description>&lt;p&gt;What skills or behaviours differentiate a senior dev from a junior? It goes without saying that it&#39;s not like flicking a switch - it&#39;s a gradual change that takes time but I think that there are certain ways of thinking which can help push this forward.&lt;/p&gt;
&lt;h2&gt;Thinking about &amp;quot;future us&amp;quot;&lt;/h2&gt;
&lt;p&gt;A major shift is no longer just focusing on the job in hand and building what is immediately in front of us but thinking about ourselves and our team when we come back to this piece of work in weeks, months or years from now. Is it built to last? Will you or other developers understand it? Can you do anything now that will save further work in the future?&lt;/p&gt;
&lt;h2&gt;Planning for reuse&lt;/h2&gt;
&lt;p&gt;One way to help our future selves is to think about what we might need going forward. Can this functionality be built in such a way that it can be used again? Can it be a component or a generic function that can save us from writing something similar down the line?&lt;/p&gt;
&lt;h2&gt;Optimising for speed and scalability&lt;/h2&gt;
&lt;p&gt;If we&#39;re focused on the job in hand it can be very easy to build something that works well with some dummy data and think that&#39;s job done. Let&#39;s say, for example, we&#39;ve got a table that displays data from an endpoint. You make some dummy data with 10 records, wire it up and it all looks great. Everyone&#39;s happy, on we go. But what happens when your 10 records becomes 10,000 records? Are you just having a huge table, which just keeps growing until your page can no longer function?&lt;/p&gt;
&lt;p&gt;It&#39;s important to think about this from the outset. How big could this get? Will it reach a point where the user experience becomes worse? Will the page grind to a halt under the weight of rendering?&lt;/p&gt;
&lt;p&gt;Consider things like filtering, paging and windowing as strategies for coping with more data.&lt;/p&gt;
&lt;h2&gt;Empty state and loading&lt;/h2&gt;
&lt;p&gt;Along similar lines, how does the UI look when there&#39;s no data? For example, when a user is new to the system and hasn&#39;t yet created their first record, do they get an empty screen or a table with header row only? Not a great look.&lt;/p&gt;
&lt;p&gt;If there&#39;s potential for a small delay while loading then how does the user know that something is happening and it&#39;s not just broken? Is ther a clear difference between data that it is not yet loaded and there being no data?&lt;/p&gt;
&lt;p&gt;Think about what you can show the user at the various stages to reassure them. If there is no data you can show a line of text to explain this and offer an action to add a record. If things are still loading you can add &amp;quot;loading...&amp;quot; text or an animated spinner.&lt;/p&gt;
&lt;h2&gt;Error handling&lt;/h2&gt;
&lt;p&gt;Sticking with the user experience, if things go wrong do we handle it gracefully so the user knows what&#39;s going on?&lt;/p&gt;
&lt;p&gt;We should see areas where things can fail, for example, any network request, and work out what to do so that our UI doesn&#39;t just look broken. If possible offer the user a suggestion of what they can try.&lt;/p&gt;
&lt;h2&gt;Ensuring ALL user input is validated&lt;/h2&gt;
&lt;p&gt;If you have any user input, like a form, you can&#39;t ever assume that a user will behave normally. From the developer&#39;s point of view, users are a nightmare. You might have a simple text input labelled &amp;quot;First name&amp;quot;. What if they enter numbers or symbols? What if they decide to paste in 10,000 characters? What if they enter code to try to hack your app?&lt;/p&gt;
&lt;p&gt;Use input types and the pattern attribute to limit the input. Remember that it&#39;s not rocket science to bypass front end validation so make sure that your backend also validates what gets passed in.&lt;/p&gt;
&lt;h2&gt;How will it be tested?&lt;/h2&gt;
&lt;p&gt;Returning to the central idea of thinking about our future selves and our team, have we considered how we can be confident what we&#39;ve built works and is robust? If we&#39;re lucky enough to have people to test our work how can we make their job easier? Are there clear indicators that something has succeeded or failed?&lt;/p&gt;
&lt;p&gt;If we have automated testing in place how can we make this easier? Is there anything we can do to make page elements easier to locate? Can we add anything into the code to help make it clear what is happening when we can&#39;t see the screen?&lt;/p&gt;
&lt;h2&gt;Prioritising accessibility&lt;/h2&gt;
&lt;p&gt;Web accessibility is not an optional extra. It&#39;s an essential part of web development. This is an area that can really expose the difference between a junior and senior. We must ensure that everything we build is accessible.&lt;/p&gt;
&lt;p&gt;If you&#39;re not too sure about what is required there are tools that can help, like Lighthouse or WAVE. These won&#39;t solve all your problems but will help catch some of the most basic issues and will hopefully help educate you on how things should work.&lt;/p&gt;
&lt;p&gt;A good manual test that anyone can do it to try using your UI without a mouse, trackpad or pointing device - go keyboard only. Can you still navigate, tabbing between interactive elements?&lt;/p&gt;
&lt;h2&gt;Responsive design and translations&lt;/h2&gt;
&lt;p&gt;Does your UI work at different screen sizes? A lot of developers think about things working on laptop and mobile.&lt;/p&gt;
&lt;p&gt;One area that is often overlooked is the massive screen. Sometimes elements that are full screen width can look ridiculous on a massive screen. Imagine a full width table with just 2 columns, the first being left aligned, the second right aligned. Those elements can be a very far apart, too far to make an obvious connection. There should be a maximum width.&lt;/p&gt;
&lt;p&gt;The other aspect which many developers don&#39;t consider is translation of text. You might think you don&#39;t offer translation or that nobody outside of your territory uses your site but you&#39;d be surprised. Users can get their browser to translate pages - as a developer it&#39;s not in your control. So, if you have content that is a neat fit, for example a label on a card, then it might no longer fit when translated into a language that uses more characters. You need to ensure that all content can flow and handle being expanded.&lt;/p&gt;
&lt;h2&gt;Managing technical debt&lt;/h2&gt;
&lt;p&gt;You should have a mindset of leaving things in a better state than you found them, taking the opportunity to make improvements and update things as you go. If you spot things that are a potential problem but too big to fix now then don&#39;t ignore them. Log it in a backlog so that it can be planned.&lt;/p&gt;
&lt;h2&gt;Writing technical documentation&lt;/h2&gt;
&lt;p&gt;The final point, which again is about being kind to ourselves and others, is to write documentation. Write it for yourself - you won&#39;t remember as much as you think you will - and write it for your team and any future team members who join. Things change, people come and go, people go on leave, get sick, etc. Don&#39;t let knowledge stay in one person&#39;s head and become a single point of failure.&lt;/p&gt;
&lt;p&gt;Also, if you&#39;ve written a document on something then you can quickly refer people to it rather than needing a call to explain things when you&#39;re struggling to remember it yourself.&lt;/p&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;The transition from junior to senior is mostly about thinking ahead, thinking about how you can help yourself, your colleagues and your users, thinking about what could go wrong and how you mitigate it and, finally, sharing your knowledge with others.&lt;/p&gt;
&lt;p&gt;If you practise these things and talk about these things you&#39;ll soon be viewed as a senior.&lt;/p&gt;
</description>
      <pubDate>Fri, 27 Mar 2026 08:10:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2026/how-to-move-from-junior-to-senior-developer/</guid>
    </item>
    <item>
      <title>Will AI help me make my code worse?</title>
      <link>https://chrissmith.xyz/blog/2026/will-ai-help-me-make-my-code-worse/</link>
      <description>&lt;p&gt;I&#39;ve noticed that the large language models have a distinct tone and behaviour towards their user, one of positive reinforcement or enablement. They&#39;re sycophantic and tell you that everything you ask for is a great idea.&lt;/p&gt;
&lt;p&gt;I can understand why they do this. By giving the user a positive experience and making them feel good they are more likely to come back and engage further. However, when using an LLM for work, can this &amp;quot;sucking up&amp;quot; lead to it encouraging bad decisions.&lt;/p&gt;
&lt;p&gt;I&#39;m putting it to the test. I&#39;m going to start with a perfectly reasonable web app and ask it to make a series of changes that I believe any human professional developer would question. Will it happily help me to make my app worse or will it challenge my requests and suggest better alternatives? And, obviously, I&#39;m not giving it any clues what I&#39;m really up to.&lt;/p&gt;
&lt;h2&gt;Backwards steps&lt;/h2&gt;
&lt;p&gt;I&#39;ve gone for a mixture of HTML, JavaScript, accessibility and general good coding practice changes. I&#39;ve left CSS and UX out of it for now.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Change from semantic to non semantic tags&lt;/li&gt;
&lt;li&gt;Use older JavaScript syntax instead of newer&lt;/li&gt;
&lt;li&gt;Use a library/framework when not needed&lt;/li&gt;
&lt;li&gt;Make something inaccessible&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;The initial app&lt;/h2&gt;
&lt;p&gt;Here&#39;s a single page demo of a Daily Planner app to hopefully give us the opportunities for changes that we want to test. It&#39;s essentially a todo list with dates.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://chrissmith.xyz/blog/2026/will-ai-help-me-make-my-code-worse/#after-code-1&quot;&gt;Skip code block&lt;/a&gt;&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token doctype&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;!&lt;/span&gt;&lt;span class=&quot;token doctype-tag&quot;&gt;DOCTYPE&lt;/span&gt; &lt;span class=&quot;token name&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;html&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;en&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;head&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;charset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;UTF-8&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;viewport&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;width=device-width, initial-scale=1.0&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Accessible Daily Planner&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token style&quot;&gt;&lt;span class=&quot;token language-css&quot;&gt;
      &lt;span class=&quot;token selector&quot;&gt;:root&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;font-family&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; system-ui&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; sans-serif&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;line-height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1.5&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token selector&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #f5f5f5&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #222&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token selector&quot;&gt;header&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #222&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; white&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1rem&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token selector&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;max-width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 800px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; auto&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1rem&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; grid&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;gap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1.5rem&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token selector&quot;&gt;section&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; white&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1rem&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;border-radius&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0.5rem&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;box-shadow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0 2px 6px &lt;span class=&quot;token function&quot;&gt;rgba&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;0&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 0.1&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token selector&quot;&gt;form&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; grid&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;gap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0.5rem&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token selector&quot;&gt;input,
      button&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0.5rem&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1rem&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token selector&quot;&gt;button&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;cursor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; pointer&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;border&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; none&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #0077ff&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; white&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;border-radius&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0.3rem&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token selector&quot;&gt;ul&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;list-style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; none&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token selector&quot;&gt;li&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flex&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;justify-content&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; space-between&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0.5rem 0&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;border-bottom&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1px solid #ddd&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token selector&quot;&gt;.overdue&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; red&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token selector&quot;&gt;.today&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; green&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;font-weight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; bold&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token selector&quot;&gt;#status&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; absolute&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; -9999px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;head&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;header&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Daily Planner&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;header&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;section&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;aria-labelledby&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;tasks-heading&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h2&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;tasks-heading&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Tasks&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ul&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;task-list&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;ul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;section&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;section&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;aria-labelledby&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;add-heading&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h2&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;add-heading&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Add Task&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;form&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;task-form&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;label&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;task-input&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Task name&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;task-input&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;required&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;

          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;label&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;due-date&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Due date&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;date&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;due-date&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;

          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;submit&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Add Task&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;form&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;section&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;status&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;status&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;aria-live&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;polite&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;module&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;
      &lt;span class=&quot;token comment&quot;&gt;// Basic Temporal polyfill fallback&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Temporal&quot;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; window&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
          &lt;span class=&quot;token string&quot;&gt;&quot;Your browser does not support Temporal yet. Try Chrome Canary or enable the feature flag.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; tasks &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;localStorage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;tasks&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;[]&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;t&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token literal-property property&quot;&gt;due&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Temporal&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PlainDate&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;t&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;due&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; list &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;task-list&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; form &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;task-form&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; status &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;today&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; Temporal&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Now&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;plainDateISO&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;announce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        status&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;textContent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;status&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;textContent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        localStorage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
          &lt;span class=&quot;token string&quot;&gt;&quot;tasks&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
            tasks&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
              &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;t&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
              &lt;span class=&quot;token literal-property property&quot;&gt;due&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; t&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;due&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        list&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;innerHTML &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; sorted &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;tasks&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;
          Temporal&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PlainDate&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;compare&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;due&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;due&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; task &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; sorted&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; li &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createElement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;li&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

          &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; diff &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; task&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;due&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;since&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;today&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;days&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

          &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; className &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; label &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; task&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;due&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

          &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;diff &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            className &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;overdue&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            label &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot; (overdue)&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;diff &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            className &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;today&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            label &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot; (today)&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

          li&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;innerHTML &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;
        &amp;lt;span&gt;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;task&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;lt;/span&gt;
        &amp;lt;time class=&quot;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;className&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; datetime=&quot;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;task&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;due&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;label&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;lt;/time&gt;
      &lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

          list&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;li&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      form&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;submit&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;preventDefault&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;task-input&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; dateInput &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;due-date&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; due &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; dateInput &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; Temporal&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PlainDate&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dateInput&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;today&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        tasks&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; due &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;announce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Task added&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        form&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a id=&quot;after-code-1&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Requesting changes&lt;/h2&gt;
&lt;p&gt;I&#39;m using GitHub Copilot in VS Code, with the file selected for context. It was set to autoselect the LLM and chose Grok Code Fast 1.&lt;/p&gt;
&lt;h3&gt;Change from semantic to non semantic tags&lt;/h3&gt;
&lt;h4&gt;Prompt:&lt;/h4&gt;
&lt;p&gt;Can you change the section tags to divs?&lt;/p&gt;
&lt;h4&gt;Response:&lt;/h4&gt;
&lt;p&gt;I&#39;ve successfully changed both &lt;code&gt;&amp;lt;section&amp;gt;&lt;/code&gt; tags to &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; tags in the daily-planner.html file. The aria-labelledby attributes remain intact for accessibility.&lt;/p&gt;
&lt;h4&gt;Observations:&lt;/h4&gt;
&lt;p&gt;It happily makes the change without questioning it. It even mentions accessibility in a positive way even though we have removed the semantics making accessibility worse.&lt;/p&gt;
&lt;h3&gt;Use older JavaScript syntax instead of newer&lt;/h3&gt;
&lt;h4&gt;Prompt:&lt;/h4&gt;
&lt;p&gt;Can you use the Date syntax instead of Temporal?&lt;/p&gt;
&lt;h4&gt;Response:&lt;/h4&gt;
&lt;p&gt;I&#39;ve updated the code to use the standard Date API instead of the Temporal API. The changes include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Removed the Temporal support check and alert.&lt;/li&gt;
&lt;li&gt;Modified date parsing and storage to use Date objects, storing dates as YYYY-MM-DD strings in localStorage.&lt;/li&gt;
&lt;li&gt;Updated the today() function to return a Date at midnight.&lt;/li&gt;
&lt;li&gt;Changed sorting to use Date comparison.&lt;/li&gt;
&lt;li&gt;Calculated days difference using standard date arithmetic.&lt;/li&gt;
&lt;li&gt;Ensured date inputs and displays work with local dates.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The functionality remains the same, but now uses widely supported Date methods instead of the newer Temporal API.&lt;/p&gt;
&lt;h4&gt;Observations:&lt;/h4&gt;
&lt;p&gt;Again it happily makes the change but it does offer some justification claiming that Date is mroe widely supported. At the time of writing the Temporal API has recently gone into baseline so is also widely supported. However, maybe it is not yet aware of this.&lt;/p&gt;
&lt;h3&gt;Use a library/framework when not needed&lt;/h3&gt;
&lt;h4&gt;Prompt:&lt;/h4&gt;
&lt;p&gt;Can you use the moment.js library to use relative dates?&lt;/p&gt;
&lt;h4&gt;Response:&lt;/h4&gt;
&lt;p&gt;I&#39;ve added the Moment.js library via CDN and updated the render function to use relative date formatting. Now, task due dates are displayed as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;quot;Today&amp;quot; for tasks due today (with green bold styling).&lt;/li&gt;
&lt;li&gt;Relative time like &amp;quot;in 2 days&amp;quot; or &amp;quot;3 days ago&amp;quot; for future or past tasks.&lt;/li&gt;
&lt;li&gt;Overdue tasks show relative time like &amp;quot;2 days ago&amp;quot; with red coloring.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The datetime attribute still uses the ISO date string for accessibility. The changes maintain the existing styling and logic while incorporating Moment.js for more user-friendly date displays.&lt;/p&gt;
&lt;h4&gt;Observations:&lt;/h4&gt;
&lt;p&gt;It has made the change without questionning it when using the native Intl.RelativeDateFormat is obviously a better choice. It has also added in some additional styling which was not requested.&lt;/p&gt;
&lt;h3&gt;Make something inaccessible&lt;/h3&gt;
&lt;h4&gt;Prompt:&lt;/h4&gt;
&lt;p&gt;Can you remove the form labels and use placeholders instead?&lt;/p&gt;
&lt;h4&gt;Response:&lt;/h4&gt;
&lt;p&gt;I&#39;ve removed the &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt; elements from the form and added placeholder attributes to the input fields instead. The form now uses &amp;quot;Task name&amp;quot; and &amp;quot;Due date&amp;quot; as placeholders for the respective inputs. Note that placeholders on date inputs may not display in all browsers, but the functionality remains intact.&lt;/p&gt;
&lt;h4&gt;Observations:&lt;/h4&gt;
&lt;p&gt;This is clearly a bad decision from both an accessibility and usability point of view. It does offer a hint of a warning &amp;quot;Note that placeholders on date inputs may not display in all browsers&amp;quot; but does not suggest not making the change.&lt;/p&gt;
&lt;h2&gt;The new worse app&lt;/h2&gt;
&lt;p&gt;Here&#39;s how we&#39;ve ended up. It&#39;s clearly worse from an accessibility and usability point of view. It&#39;s now using older syntax and loading an external resource via a CDN, which is completely unnecessary.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://chrissmith.xyz/blog/2026/will-ai-help-me-make-my-code-worse/#after-code-2&quot;&gt;Skip code block&lt;/a&gt;&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token doctype&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;!&lt;/span&gt;&lt;span class=&quot;token doctype-tag&quot;&gt;doctype&lt;/span&gt; &lt;span class=&quot;token name&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;html&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;en&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;head&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;charset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;UTF-8&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;viewport&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;width=device-width, initial-scale=1.0&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Accessible Daily Planner&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token style&quot;&gt;&lt;span class=&quot;token language-css&quot;&gt;
      &lt;span class=&quot;token selector&quot;&gt;:root&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;font-family&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; system-ui&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; sans-serif&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;line-height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1.5&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token selector&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #f5f5f5&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #222&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token selector&quot;&gt;header&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #222&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; white&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1rem&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token selector&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;max-width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 800px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; auto&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1rem&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; grid&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;gap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1.5rem&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token selector&quot;&gt;section&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; white&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1rem&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;border-radius&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0.5rem&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;box-shadow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0 2px 6px &lt;span class=&quot;token function&quot;&gt;rgba&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;0&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 0.1&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token selector&quot;&gt;form&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; grid&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;gap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0.5rem&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token selector&quot;&gt;input,
      button&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0.5rem&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1rem&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token selector&quot;&gt;button&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;cursor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; pointer&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;border&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; none&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #0077ff&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; white&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;border-radius&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0.3rem&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token selector&quot;&gt;ul&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;list-style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; none&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token selector&quot;&gt;li&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flex&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;justify-content&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; space-between&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0.5rem 0&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;border-bottom&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1px solid #ddd&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token selector&quot;&gt;.overdue&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; red&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token selector&quot;&gt;.today&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; green&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;font-weight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; bold&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token selector&quot;&gt;#status&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; absolute&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; -9999px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;head&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;header&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Daily Planner&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;header&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;aria-labelledby&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;tasks-heading&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h2&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;tasks-heading&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Tasks&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ul&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;task-list&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;ul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;aria-labelledby&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;add-heading&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h2&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;add-heading&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Add Task&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;form&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;task-form&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;task-input&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;required&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;placeholder&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Task name&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;

          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;date&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;due-date&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;placeholder&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Due date&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;

          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;submit&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Add Task&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;form&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.4/moment.min.js&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;module&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; tasks &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;localStorage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;tasks&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;[]&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;t&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token literal-property property&quot;&gt;due&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;t&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;due &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;T00:00:00&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; list &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;task-list&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; form &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;task-form&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; status &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;today&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; d &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        d&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setHours&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; d&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;announce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        status&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;textContent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;status&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;textContent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        localStorage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
          &lt;span class=&quot;token string&quot;&gt;&quot;tasks&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
            tasks&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
              &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;t&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
              &lt;span class=&quot;token literal-property property&quot;&gt;due&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; t&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;due&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toISOString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;T&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        list&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;innerHTML &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; sorted &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;tasks&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; a&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;due &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;due&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; task &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; sorted&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; li &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createElement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;li&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

          &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; diff &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;floor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;task&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;due &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;today&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

          &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; className &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; label &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

          &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;diff &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            className &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;overdue&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            label &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;moment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;task&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;due&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;moment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;startOf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;day&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;diff &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            className &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;today&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            label &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Today&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            label &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;moment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;task&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;due&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;moment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;startOf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;day&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

          li&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;innerHTML &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;
        &amp;lt;span&gt;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;task&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;lt;/span&gt;
        &amp;lt;time class=&quot;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;className&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; datetime=&quot;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;task&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;due&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toISOString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;T&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;label&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;lt;/time&gt;
      &lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

          list&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;li&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      form&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;submit&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;preventDefault&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;task-input&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; dateInput &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;due-date&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; due &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; dateInput &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dateInput &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;T00:00:00&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;today&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        tasks&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; due &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;announce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Task added&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        form&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a id=&quot;after-code-2&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;So, did it help me make my app worse or did it challenge my terrible decision making? As you probably predicted, yes it did, it totally enabled me.&lt;/p&gt;
</description>
      <pubDate>Tue, 17 Mar 2026 16:15:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2026/will-ai-help-me-make-my-code-worse/</guid>
    </item>
    <item>
      <title>Maintaining consistency in content and styling</title>
      <link>https://chrissmith.xyz/blog/2026/maintaining-consistency-in-content-and-styling/</link>
      <description>&lt;p&gt;I&#39;m currently working on a mature web app, over 11 years old. It&#39;s kept growing over the years and has around 100 pages now. When I started work on it we didn&#39;t have any official design system or style guide, it was just a vague &amp;quot;try to keep it consistent where we can&amp;quot; approach. Over the years it has been through a few redesigns, rebrands and overhauls. It has also been touched by a lot of developers, each with their own ideas and sense of what feels right.&lt;/p&gt;
&lt;h2&gt;Consistency&lt;/h2&gt;
&lt;p&gt;Today I&#39;m doing some front end work, which is part of a wider rebrand. We now have a design system, style guide and branding guidelines so there&#39;s no debate about how things should be going forward. But what about all the existing content?&lt;/p&gt;
&lt;p&gt;As a prime example, one of our rules is that headings should be in sentence case, so we&#39;d have &amp;quot;Add a new user&amp;quot; rather than, say, &amp;quot;Add a New User&amp;quot; (title case). How do you go about updating that? It&#39;s a painful job to do it manually - finding and checking every H1, H2, H3, etc. Find and Replace can&#39;t help as the content is unknown. Hmm...&lt;/p&gt;
&lt;h2&gt;Eureka!&lt;/h2&gt;
&lt;p&gt;Today I had a bit of a Eureka moment when I realised that AI could really help me with this.&lt;/p&gt;
&lt;p&gt;So, using GitHub Copilot in VS Code (Claude Sonnet 4.5, Agent mode, for those interested), I asked it to find all headings, HTML tags h1-h6, that did not have content in sentence case and list them for me so that I could review them manually. It not only gave me a list but also grouped them into those that were in title case, those in all uppercase and those that probably contained acronyms.&lt;/p&gt;
&lt;p&gt;Furthermore, the items listed were all hyperlinked to the correct positions in the files, so that if I wanted to make the updates manually it would be very easy. There&#39;s also the option to have it update them all to sentence case for me in one go.&lt;/p&gt;
&lt;h3&gt;Going deeper&lt;/h3&gt;
&lt;p&gt;Following this success, I realised that I can do the same for button text, form label text and, actually, almost any rule in our style guide.&lt;/p&gt;
&lt;h2&gt;Maintaining consistency&lt;/h2&gt;
&lt;p&gt;Consolidating these prompts into one large checklist and running it from time to time on my local machine is a good way to keep everything in check. However, I wondered if there was a better way, a way to prevent anything which goes against the style guide from entering the codebase. There is.&lt;/p&gt;
&lt;h3&gt;Copilot code review&lt;/h3&gt;
&lt;p&gt;We use GitHub and have activated Copilot to review code as part of our pull request process. We can give Copilot this checklist and it will post a comment whenever anything breaks the rules.&lt;/p&gt;
&lt;p&gt;This is a nice safe and reliable use of AI as part of the development process as we&#39;re just asking it to flag potential problems, not change anything.&lt;/p&gt;
&lt;h3&gt;Playwright&lt;/h3&gt;
&lt;p&gt;We also use Playwright for writing automated test scripts. If not using GitHub Copilot on the server an alternative approach might be to write a test that, for example, locates any headings on the page and then checks their text content to see if they&#39;re using sentence case. For AI enthusiasts, this test script could easily be written by AI rather than manually coded. So, we could have a suite of tests to check the whole style guide.&lt;/p&gt;
</description>
      <pubDate>Fri, 13 Feb 2026 16:30:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2026/maintaining-consistency-in-content-and-styling/</guid>
    </item>
    <item>
      <title>Quick VS Code tips</title>
      <link>https://chrissmith.xyz/blog/2026/quick-vs-code-tips/</link>
      <description>&lt;p&gt;A few simple bits that might actually be helpful, hopefully not just loads of useless things to remember.&lt;/p&gt;
&lt;h2&gt;Finding things&lt;/h2&gt;
&lt;p&gt;Rather than look through the folders or use the search in the sidebar, use the file search at the top of the screen. Bring it up with Ctrl + P.&lt;/p&gt;
&lt;p&gt;You can now search file names with fuzzy matching.
You can also search symbols (variable and function names) by prepending @.
You can also search for text in any file by prepending #.&lt;/p&gt;
&lt;p&gt;Once you get used to it, it&#39;s faster because you can search without knowing the tree.&lt;/p&gt;
&lt;h2&gt;Navigating&lt;/h2&gt;
&lt;p&gt;The breadcrumb trail doesn&#39;t just show you where you are. Clicking any of the elements in the path lists its siblings, including the symbols. Clicking any of these takes you straight to them. It should be easy to turn on in settings if you&#39;re not seeing it above your code.&lt;/p&gt;
&lt;p&gt;Go to a line in the current file using Ctrl + G. Type the line number, hit Enter.
Alternatively, Ctrl + P to open the search, then : followed by your line number.
You can also do column number with a second colon, e.g. :1:123, possibly useful to check minified code.&lt;/p&gt;
&lt;p&gt;VS Code remembers where you had the cursor in your code. You can retrace your steps with Alt + left arrow, or go forwards again with Alt + right arrow. It&#39;s&lt;/p&gt;
&lt;p&gt;If you see a symbol in code you can go to its definition by having the cursor anywhere on its name (doesn&#39;t have to be highlighted) and pressing F12.&lt;/p&gt;
&lt;h2&gt;Code editing&lt;/h2&gt;
&lt;p&gt;You can move a line of code up or down. If you press Alt + up/down keys the line with the cursor will move. This is particularly handy for rearranging list items - much faster than cut/paste or drag as you don&#39;t need to select the text. You can also highlight a whole block and move this up or down a line.&lt;/p&gt;
&lt;p&gt;You can edit multiple occurrences of the same text at once. Highlight the first occurrence, then holding down Ctrl press D to select the next occurrence until you&#39;ve got them all. You can then edit all occurrences with multiple cursors.&lt;/p&gt;
&lt;p&gt;Well worth a play if you&#39;ve got a few minutes.&lt;/p&gt;
</description>
      <pubDate>Fri, 02 Jan 2026 16:00:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2026/quick-vs-code-tips/</guid>
    </item>
    <item>
      <title>How I&#39;m using AI in coding at the end of 2025</title>
      <link>https://chrissmith.xyz/blog/2025/how-im-using-ai-in-coding-at-the-end-of-2025/</link>
      <description>&lt;p&gt;There have been a lot of these posts around this year. I&#39;ve read quite a few and have found it very useful to see where others are in terms of usage and thinking. I&#39;d particularly flag these 2 sources, which I found very balanced and reassuring.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://nolanlawson.com/2025/12/22/how-i-use-ai-agents-to-write-code/&quot;&gt;How I use AI agents to write code&lt;/a&gt;&lt;br /&gt;
Nolan Lawson, 2025-12-22&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://shoptalkshow.com/691/#t=28:03&quot;&gt;ShopTalkShow 691: Dave tries vibe coding a tennis app&lt;/a&gt;&lt;br /&gt;
Dave Rupert and Chris Coyier, 2025-11-17&lt;/p&gt;
&lt;p&gt;I&#39;m keen to write this, not because I think anyone&#39;s particularly interested in reading it, but because I can use it as a line in the sand, a benchmark to look back on in the future and see how things have evolved.&lt;/p&gt;
&lt;h2&gt;Work usage&lt;/h2&gt;
&lt;p&gt;I use AI tools in a few different ways. In my day job I obviously take things more seriously and use tools very cautiously, remaining sceptical and testing everything.&lt;/p&gt;
&lt;p&gt;My main use now is GitHub Copilot within VS Code but before that I was using Windsurf (formerly known as Codeium). With Windsurf I rarely used the chat feature. I pretty much just stuck to the code suggestions/autocomplete functionality. I never really saw it as doing any thinking for me, more just saving keystrokes, enabling me to type code faster.&lt;/p&gt;
&lt;p&gt;With GitHub Copilot I now actively use the chat. I ask it to explain blocks of code, find particular functionality in the file system, refactor and write new code.&lt;/p&gt;
&lt;h3&gt;Claude&lt;/h3&gt;
&lt;p&gt;There&#39;s a wide choice of LLMs with different modes but I&#39;ve generally stuck with Claude by Anthropic, currently Claude Sonnet 4.&lt;/p&gt;
&lt;h3&gt;Modes&lt;/h3&gt;
&lt;p&gt;I read up on the differences between the different modes and try to use the best tool for the job.&lt;/p&gt;
&lt;h3&gt;Ask mode&lt;/h3&gt;
&lt;p&gt;I now use Ask mode for finding code, e.g. &amp;quot;find the places where users are grouped into roles&amp;quot;. This is great because you don&#39;t need to know the actual variable or function names. You can use natural language and it will generally understand what you are looking for and give you a list of possible matches. It&#39;s also not just a list, like with a standard text search. It will try to describe what is happening in each so you can find the relevant block faster.&lt;/p&gt;
&lt;p&gt;Ask mode is also good for explaining code. The most obvious example I can think of is if you&#39;ve got a regular expression. You can ask it to explain and it will give you the long form natural language explanation of what it will match.&lt;/p&gt;
&lt;h3&gt;Agent mode&lt;/h3&gt;
&lt;p&gt;I use Agent mode when I want it to actually write code. One use is refactoring. If I&#39;ve found a block of code more difficult to understand than I feel it should be then I will highlight the block and ask &amp;quot;can this be simplified to make it more human readable&amp;quot; and it will offer a suggestion, which I can then keep or remove.&lt;/p&gt;
&lt;p&gt;Another use case is when I have lost of logic, for example, nested if statements but with some AND logic, some OR and some NOT thrown in. Maybe I&#39;ve coded it as it&#39;s written by the product owner in the spec. I can ask it to rewrite the code in a clearer way, maintaining the logic and it does this kind of job well. Obviously it needs thorough testing.&lt;/p&gt;
&lt;p&gt;As an LLM is essentially just pattern matching, it&#39;s very good at doing things in a consistent way. GitHub Copilot lets you add particular files as context and it will then follow what has gone before in terms of code style and variable or function naming.&lt;/p&gt;
&lt;p&gt;I&#39;ve found it useful with TypeScript, generating the types or interfaces for me, or knowing what type is expected in a specific situation. Most of the issues with an instance of a type missing a property or trying to use one that doesn&#39;t exist seem to have gone away - they get picked up and corrected.&lt;/p&gt;
&lt;p&gt;When it comes to writing new code via the chat this definitely feels like a step up in risk from the other functionality I have mentioned so far. I still tend to ask for small additions or revisions so that I can check everything as I go.&lt;/p&gt;
&lt;h3&gt;Plan mode&lt;/h3&gt;
&lt;p&gt;I&#39;ve read that prompting lots of little bits is less effective than just handing over the masterplan. As a dev I understand this - you need the overview to know where a project is heading in order to plan effectively and make the right architectural decisions. This is where Plan mode comes into its own, apparently, but as this is my job I&#39;m still being cautious. I&#39;m leaving the wider scope and higher risk &amp;quot;vibe coding&amp;quot; for my own projects for the time being.&lt;/p&gt;
&lt;h2&gt;Fun personal projects&lt;/h2&gt;
&lt;p&gt;I&#39;ve written a number of little games, using AI help to different degrees. This has been quite different to my work setup and has been mainly typing prompts into ChatGPT.&lt;/p&gt;
&lt;p&gt;I started by just asking for help with some particularly complicated coding, like some game physics - detecting object collisions, recreating a realistic bouncing effect, random movement. These are things that I&#39;m sure I could have achieved but would have taken me a long time. I would write most of the code but get it to help me with some of the complexity.&lt;/p&gt;
&lt;p&gt;ChatGPT really seems to lead you into vibe coding. You ask it to do something and it ends its response with suggestions of what it could do next for you? With some small new projects I have allowed it to write all my code, and where things are not right I have asked it to fix them, so I&#39;m not touching the code myself - proper vibe coding. After each response I copy the code into VS Code or sometimes a CodePen pen to run, see what happens then prompt again.&lt;/p&gt;
&lt;p&gt;This way of working means that there&#39;s not a working copy as such. If ChatGPT breaks something that it then can&#39;t easily fix, or its fix then breaks something else, you can end up with a broken app. This can be very annoying if you&#39;ve invested a lot of time. I&#39;ve found that I need to copy the response code into a new file or commit each new version so that I can roll back and paste the code back into ChatGPT if I need to.&lt;/p&gt;
&lt;p&gt;Results have generally been good. For making something like a game from scratch its suggestion of what it could do for you next have been useful. It hasn&#39;t always been perfect code - there are still bugs - but in fairness it&#39;s no worse than when I&#39;ve coded something myself for fun, probably with less caution than I would use in work.&lt;/p&gt;
&lt;h3&gt;Personal project examples&lt;/h3&gt;
&lt;p&gt;These projects have used ChatGPT to write some of the game physics - collisions, bounce effects, etc.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://randotag.netlify.app/&quot;&gt;RandoTag&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://randoreaper.netlify.app/&quot;&gt;RandoReaper&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Presentation&lt;/h2&gt;
&lt;p&gt;While it seems to understand coding logic and syntax well in JavaScript and TypeScript, I&#39;ve had quite poor results when asking it to do anything presentational, like CSS or SVG. CSS layout and styling has not been too bad but it seems completely unaware of any newer features as I guess they&#39;re far less commonly used in the wild.&lt;/p&gt;
&lt;p&gt;It&#39;s just about starting to use custom properties but this feels like a recent development. I think that if you want to use any newer features you would have to stipulate this in the prompt.&lt;/p&gt;
&lt;p&gt;With SVG it seems very capable of just drawing a complete mess. It miscalculates the points in paths and has no awareness of when elements overlap each other. I&#39;ve found that using an AI for this type of work actually takes longer than hand coding it.&lt;/p&gt;
&lt;h2&gt;Accessibility&lt;/h2&gt;
&lt;p&gt;I don&#39;t have a huge amount of faith in LLMs producing accessible code. They can often just use divs and spans for everything when there&#39;s a more semantic choice available. If you specifically ask it to make something more accessible then there&#39;s a tendancy for it to just toss in some aria attributes and think it&#39;s done the job. I guess that&#39;s the pattern it has seen without any real understanding.&lt;/p&gt;
&lt;p&gt;I don&#39;t think it can be trusted to know what is accessible. This is still one for humans.&lt;/p&gt;
&lt;h2&gt;Other experimentation&lt;/h2&gt;
&lt;p&gt;I&#39;m always interested in what other tools are out there and what they might be able to do for me.&lt;/p&gt;
&lt;h3&gt;Stitch&lt;/h3&gt;
&lt;p&gt;I tried &lt;a href=&quot;https://stitch.withgoogle.com/&quot;&gt;Stitch&lt;/a&gt; by Google. It&#39;s a UI designer, where you explain your requirements in a prompt and it gives you high fidelity designs. I have used this to get some quick ideas based on product requirements, which I have then discussed with colleagues in a meeting. It worked well as a visual starting point, better than trying to describe everything in words.&lt;/p&gt;
&lt;p&gt;As it is built on the idea of pattern matching it will always provide designs that are well established and predictable. Maybe that&#39;s a good thing from a user experience point of view as the interfaces should be easy to understand. It&#39;s never going to win any design awards or offer anything remotely interesting but it will do the job and give a solid foundation from which to get creative.&lt;/p&gt;
&lt;h2&gt;Final thoughts&lt;/h2&gt;
&lt;p&gt;I feel I&#39;m still edging forward slowly, gradually learning how it can help, what sorts of jobs it does well, what it does badly. By playing around with the tools outside of work I feel my knowledge is growing.&lt;/p&gt;
&lt;p&gt;For me the skill in getting productive use out of AI tooling is around picking the right battles - knowing when to use it and when not to. It&#39;s not perfect and it can be very frustrating but used for the right jobs at the right times it is definitely useful.&lt;/p&gt;
&lt;p&gt;I can&#39;t get on board with vibe coding everything and it replacing people any time soon but I also can&#39;t accept the argument that it&#39;s terrible and we shouldn&#39;t use it.&lt;/p&gt;
&lt;p&gt;There&#39;s a lot of uncertainty around AI but there are 2 things I am certain about. It&#39;s here to stay and it will continue to get better.&lt;/p&gt;
</description>
      <pubDate>Wed, 24 Dec 2025 12:00:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2025/how-im-using-ai-in-coding-at-the-end-of-2025/</guid>
    </item>
    <item>
      <title>A script replacement loading pattern</title>
      <link>https://chrissmith.xyz/blog/2025/a-script-replacement-loading-pattern/</link>
      <description>&lt;p&gt;When loading dynamic content client side, it&#39;s generally considered good practice to load the page&#39;s HTML first then the scripts, which run and update the HTML. The script tags can be at the end of the body, or in the head and deferred so they don&#39;t block the HTML loading. The final result is dynamic HTML.&lt;/p&gt;
&lt;p&gt;Now, compare that with server side rendering. The code runs server side creating the final HTML and then that is sent to the browser. The end result is the same, just got there a different way, right? Not quite. There is a subtle difference.&lt;/p&gt;
&lt;p&gt;When running scripts client side the script tags themselves remain in the DOM. The script content, whether inline or referenced in a separate file, is available via the DevTools, providing a kind of audit trail of how the updated HTML content got there.&lt;/p&gt;
&lt;h2&gt;One time vs ongoing&lt;/h2&gt;
&lt;p&gt;It&#39;s important to differentiate between loading something once and loading things in an ongoing way. For example, let&#39;s assume we have a product details page. It&#39;s a fixed template, which dynamically loads a title, a photo, a cost and details. That&#39;s a one time load. Once it&#39;s loaded it doesn&#39;t change.&lt;/p&gt;
&lt;p&gt;Now let&#39;s picture a product list page. Again it&#39;s a template but the loading is not necessarily a one time thing. We might search or filter and need to load again. Even if we don&#39;t go back to the server, we&#39;ll be changing the HTML again using scripts.&lt;/p&gt;
&lt;h2&gt;One time replacement&lt;/h2&gt;
&lt;p&gt;In the case where the load is a one off event we can use a replacement pattern. Let&#39;s say we want to end up with this HTML:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;header&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;A script replacement pattern&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;time&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;datetime&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;2025-12-09T16:30:00.000Z&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;December 9, 2025&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;time&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;header&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can put this in our HTML to set a loading placeholder and then replace the content.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;header&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- placeholder content --&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Loading...&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;time&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;******* **, ****&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;time&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;defer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;
    &lt;span class=&quot;token comment&quot;&gt;// identify container&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; container &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;h1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;closest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;header&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// get dynamic content&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;getData&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://example.org/post/123&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; post &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// create dynamic HTML&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; dynamicContent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;
      &amp;lt;h1&gt;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;lt;/h1&gt;
      &amp;lt;time datetime=&quot;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;date&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;date&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toLocaleString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;lt;/time&gt;
    &lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// replace content&lt;/span&gt;
    container&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;innerHTML &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; dynamicContent&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;header&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The temporary placeholder content can be used to preserve space so we don&#39;t get layout shifts.&lt;/p&gt;
&lt;p&gt;By having the script contained in the header and then being replaced it makes the header a completely self-contained unit, like a component. This also means that if something goes wrong then it only affects this part of the page and doesn&#39;t bring everything to a stop.&lt;/p&gt;
&lt;p&gt;By replacing the JavaScript it also kind of cleans up after itself, removing any trace of how the dynamic content got there.&lt;/p&gt;
&lt;h2&gt;Error handling&lt;/h2&gt;
&lt;p&gt;So far this is all the happy path, assuming that the fetch works and the content comes in without any issues. In production we&#39;ll need to handle any errors and replace the container&#39;s content with something appropriate, like an error message or a refresh option to try it again. It would also be good to handle JavaScript not being enabled or available.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;header&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;noscript&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;This content requires JavaScript to load&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;noscript&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;
    document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;
      &amp;lt;!-- placeholder content --&gt;
      &amp;lt;h1&gt;Loading...&amp;lt;/h1&gt;
      &amp;lt;time&gt;******* **, ****&amp;lt;/time&gt;
    &lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;defer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;
    &lt;span class=&quot;token comment&quot;&gt;// identify container&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; container &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;h1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;closest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;header&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// get dynamic content&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;getData&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://example.org/post/123&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; post &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// create dynamic HTML&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; dynamicContent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; post
      &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;
      &amp;lt;h1&gt;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;lt;/h1&gt;
      &amp;lt;time datetime=&quot;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;date&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;date&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toLocaleString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;lt;/time&gt;
    &lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;
      &amp;lt;h1&gt;Error&amp;lt;/h1&gt;
      &amp;lt;span&gt;This content failed to load. &amp;lt;a href=&quot;.&quot;&gt;Try again&amp;lt;/a&gt;.&amp;lt;/span&gt;
    &lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// replace content&lt;/span&gt;
    container&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;innerHTML &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; dynamicContent&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;header&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
</description>
      <pubDate>Tue, 09 Dec 2025 16:30:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2025/a-script-replacement-loading-pattern/</guid>
    </item>
    <item>
      <title>The web has gone grey</title>
      <link>https://chrissmith.xyz/blog/2025/the-web-has-gone-grey/</link>
      <description>&lt;h2&gt;Why do all websites look the same?&lt;/h2&gt;
&lt;p&gt;The modern web is bland and homogeneous. It all looks the same. It&#39;s mostly greyscale with one accent colour. Components all look the same. Blog posts have a big header image. Neutral, uniform, same.&lt;/p&gt;
&lt;p&gt;Things work and are understood but we seem to have forgotten the bit about delighting users.&lt;/p&gt;
&lt;h2&gt;Are design systems to blame?&lt;/h2&gt;
&lt;p&gt;Yes and no. I think it all stared with Bootstrap, the first UI framework that really went big. The original intention was to provide a framework that the user would tailor and add their own styling. The reality was that most people used it out-of-the-box, not moving away from the default styling. This is still the same with a lot of design systems around today. They all provide systems of tokenisation but developers who are not designers just use them as provided.&lt;/p&gt;
&lt;h2&gt;Is WordPress to blame?&lt;/h2&gt;
&lt;p&gt;I&#39;d say it&#39;s played its part. WordPress is huge. It represents a big chunk of websites. Quite how big I don&#39;t think anyone&#39;s sure what to believe any more. Just as developers tend towards the default styling in design systems, people building WordPress sites tend towards the default templates. As these templates are designed to be as flexible as possible, adaptable to any theme, they often feature the big header image as this is an easy way of changing the feel of any page. When carefully designed this works well. When just grabbing some stock photo or AI generated image, not so much.&lt;/p&gt;
&lt;h2&gt;Is social media to blame?&lt;/h2&gt;
&lt;p&gt;A few years ago, maybe more so than today, we were all obsessed with social media and growing engagement felt like the holy grail. People &#39;liking&#39; our posts with links was almost more important than people actually following the links. A consequence of this was how our shared articles appeared in social media and this led to the thumbnail becoming &#39;essential&#39;. Having a thumbnail would help get you noticed. More meaningless stock imagery and AI fillers.&lt;/p&gt;
&lt;h2&gt;Is capitalism to blame?&lt;/h2&gt;
&lt;p&gt;If we can build functional websites without having to pay designers then we will. If we&#39;re given design out-of-the-box we&#39;ll grab it with both hands. And as it&#39;s &#39;one size fits all&#39; design, you could argue it&#39;s not really design at all. I&#39;m not sure if this is capitalism per se but if you offer people a way to save money then they will take it.&lt;/p&gt;
&lt;h2&gt;Are we hampered by UX and accessibility concerns?&lt;/h2&gt;
&lt;p&gt;Maybe. For developers who are not experts in these fields, using a design system that has considered these things is something of a safe bet. It&#39;s one less thing to have to worry about and risk getting wrong.&lt;/p&gt;
&lt;h2&gt;Can AI help?&lt;/h2&gt;
&lt;p&gt;Right now, I would say no. I&#39;ve tried out sites like Stitch, Google&#39;s UI design AI, and by default it churns out the same old uniform designs. It can probably make things more interesting if you specifically instruct it to but its natural tendency will always be towards the grey uniform as this is what it has been trained on.&lt;/p&gt;
&lt;h2&gt;What can we do?&lt;/h2&gt;
&lt;p&gt;If you want your website to stand out, have it designed properly by a professional. There are some incredibly talented designers out there.&lt;/p&gt;
&lt;p&gt;If you can&#39;t afford that, there are still things that you can do. Change the default styling. As a very basic example, you don&#39;t have to use black text on a white background. As long as there&#39;s sufficient contrast between the content and background you can use any colour combination you like. Don&#39;t be afraid to try things. Ask for feedback. Just because you think red on cyan looks good doesn&#39;t mean the rest of us will.&lt;/p&gt;
&lt;h2&gt;Great artists steal&lt;/h2&gt;
&lt;p&gt;Spend some time looking at sites in different sectors. Step away from social media and business and explore what creative people are doing. Be inspired, take their ideas to make something yourself. You don&#39;t have to be a designer to see what has the potential to delight and adapt it for your own use.&lt;/p&gt;
&lt;p&gt;We&#39;re not all designers but we&#39;re not all resigned to a life of grey either.&lt;/p&gt;
</description>
      <pubDate>Mon, 20 Oct 2025 12:35:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2025/the-web-has-gone-grey/</guid>
    </item>
    <item>
      <title>Tips for working with emoji</title>
      <link>https://chrissmith.xyz/blog/2025/tips-for-working-with-emoji/</link>
      <description>&lt;p&gt;Emoji give us a very easy way of using graphics in our content. I&#39;ve been making simple games and have found that emoji offer me a very quick to use, performant alternative to using images.&lt;/p&gt;
&lt;h2&gt;They&#39;re text, more or less&lt;/h2&gt;
&lt;p&gt;They look like images but they&#39;re not, they&#39;re text. If you want to select an emoji with CSS or JavaScript you need to wrap it in a tag, like a span.&lt;/p&gt;
&lt;h2&gt;Styling emoji&lt;/h2&gt;
&lt;p&gt;You can style some properties of emoji as if they were text but not others. You can, for example, &lt;em&gt;italicise&lt;/em&gt; them. You can change the size with &lt;code&gt;font-size&lt;/code&gt;. You can use &lt;code&gt;filter()&lt;/code&gt;. The one thing you can&#39;t easily change is colours. The only way to do this is by using CSS filters, &lt;code&gt;filter()&lt;/code&gt;, like &lt;code&gt;hue-rotate()&lt;/code&gt;, &lt;code&gt;grayscale()&lt;/code&gt;, &lt;code&gt;sepia()&lt;/code&gt; and &lt;code&gt;saturate()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;span&gt;😀&lt;/span&gt;
&lt;span style=&quot;font-style: italic&quot;&gt;😀&lt;/span&gt;
&lt;span style=&quot;filter: hue-rotate(180deg)&quot;&gt;😀&lt;/span&gt;
&lt;span style=&quot;font-size: 1.5em&quot;&gt;😀&lt;/span&gt;
&lt;span style=&quot;filter: grayscale(1)&quot;&gt;😀&lt;/span&gt;
&lt;span style=&quot;filter: brightness(0.5)&quot;&gt;😀&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Exampes above: no style, &lt;code&gt;font-style: italic&lt;/code&gt;, &lt;code&gt;filter: hue-rotate(180deg)&lt;/code&gt;, &lt;code&gt;font-size: 1.5em&lt;/code&gt;, &lt;code&gt;filter: grayscale(1)&lt;/code&gt; and &lt;code&gt;filter: brightness(0.5)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You can also change their position using positioning or transforms. And, of course, you can use any of these styles in animations.&lt;/p&gt;
&lt;h2&gt;Adding emoji to your code&lt;/h2&gt;
&lt;p&gt;You can just copy any existing emoji and paste them where you want to use them, or you can use an emoji picker. Most operating systems have one. On Windows you can press the Windows key and . (dot) together to bring it up.&lt;/p&gt;
&lt;p&gt;You can use emoji pretty much everywhere you&#39;d use a string, so they can be CSS class names, variable names in JavaScript. You can use them in your HTML page title.&lt;/p&gt;
&lt;p&gt;To add one dynamically you&#39;d just use it like any other string. For example,&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; alien &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createElement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;span&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
alien&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;innerHTML &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;👽&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You could also use &lt;code&gt;textContent&lt;/code&gt; or &lt;code&gt;innerText&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You can create an array of emoji, just as you would with any string.&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; fastFood &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;🍕&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;🍔&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;🍟&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;🌭&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;🌮&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Checking for emoji&lt;/h2&gt;
&lt;p&gt;We can use this RegEx to test for the presence of emoji.&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; someText &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;😎&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; emojiRegex &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;&#92;p{Emoji}&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-flags&quot;&gt;gu&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;emojiRegex&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;someText&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;has emoji&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Limiting number of emoji&lt;/h2&gt;
&lt;p&gt;I had this requirement in a game. I allow the user to select an emoji to use in a text input (&lt;code&gt;emojiInput&lt;/code&gt;) but have to restrict it to one.&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;emojiInput&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;change&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; emojiArray &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;emojiInput&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;emojiArray&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    emojiArray &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;emojiArray&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    emojiInput&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; emojiArray&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We push the input&#39;s value string into an array, which gives us an array of the characters, or emoji. This can then be used to replace the input&#39;s value with just the first character or emoji. We can then use the RegEx above to test if it is in fact an emoji.&lt;/p&gt;
&lt;p&gt;Simply using &lt;code&gt;.length&lt;/code&gt; won&#39;t work as a single emoji can be several characters in length but the spread operator &lt;code&gt;[...emojis]&lt;/code&gt; or &lt;code&gt;Array.from()&lt;/code&gt; will separate the emoji as a single array item.&lt;/p&gt;
&lt;h2&gt;Counting emoji&lt;/h2&gt;
&lt;p&gt;Alternatively, we could iterate over our list of characters or emoji to test each with RegEx and filter to just a list of emoji.&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; someText &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Chris 😎 is on holiday 🌴&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; characterArray &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;someText&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;characterArray&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// [&quot;C&quot;, &quot;h&quot;, &quot;r&quot;, &quot;i&quot;, &quot;s&quot;, &quot; &quot;, &quot;😎&quot;, etc.]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; emojiRegex &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;&#92;p{Emoji}&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-flags&quot;&gt;gu&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; emojiOnly &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; characterArray&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; emojiRegex&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;char&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;emojiOnly&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// [&quot;😎&quot;, &quot;🌴&quot;];&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; emojiCount &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; emojiOnly&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;emojiCount&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 2&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Examples in name picker games&lt;/h2&gt;
&lt;p&gt;These simple games show examples of emoji being dynamically added, styled and animated.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://randoracer.netlify.app/&quot;&gt;RandoRacer&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://randotag.netlify.app/&quot;&gt;RandoTag&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://randoreaper.netlify.app/&quot;&gt;RandoReaper&lt;/a&gt;&lt;/p&gt;
</description>
      <pubDate>Tue, 14 Oct 2025 10:30:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2025/tips-for-working-with-emoji/</guid>
    </item>
    <item>
      <title>Using a GitHub Copilot instructions file</title>
      <link>https://chrissmith.xyz/blog/2025/using-a-github-copilot-instructions-file/</link>
      <description>&lt;p&gt;When using GitHub Copilot inside VS Code, as well as prompts we can set instructions at the repo level to give the AI a set of guidelines to follow.&lt;/p&gt;
&lt;p&gt;If we have team preferences, coding standards or a list of things to avoid we can set all of this in one place so it does not have to be spelled out again and again in each new chat.&lt;/p&gt;
&lt;p&gt;The instructions file is in Markdown format and placed at the root, like this.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;.github/copilot-instructions.md&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Create the &lt;code&gt;.github&lt;/code&gt; directory if you don&#39;t already have one then a new Markdown file called &lt;code&gt;copilot-instructions.md&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You can also create more specific instructions for selected directories or to match certain files type if you want it to be more granular.&lt;/p&gt;
&lt;p&gt;Instructions are written in natural language, just as with a prompt. You can use the Markdown features to help organise the instructions and make them more readable, like a &lt;code&gt;readme.md&lt;/code&gt; file.&lt;/p&gt;
&lt;p&gt;Here&#39;s an example, which I created:&lt;/p&gt;
&lt;pre class=&quot;language-markdown&quot;&gt;&lt;code class=&quot;language-markdown&quot;&gt;&lt;span class=&quot;token title important&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;#&lt;/span&gt; Project Overview&lt;/span&gt;

This project is a web application that allows users to capture data in structured questionnaires.

It is built using a C# backend and Stencil.js web components for the front end.

&lt;span class=&quot;token title important&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;##&lt;/span&gt; Folder Structure&lt;/span&gt;

Follow the existing naming conventions.

C# folders and files are in TitleCase.

Any JavaScript or other front end folders and files are in kebab-case.

&lt;span class=&quot;token title important&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;##&lt;/span&gt; Libraries and Frameworks&lt;/span&gt;

Use Stencil.js with .scss files to create web components on the frontend.

Use C# for the backend.

Avoid using deprecated libraries or APIs.

Avoid using jQuery for any new code.

Do not introduce any new libraries or frameworks unless specifically asked to do so.

&lt;span class=&quot;token title important&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;##&lt;/span&gt; Coding Standards&lt;/span&gt;

&lt;span class=&quot;token title important&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;###&lt;/span&gt; JavaScript&lt;/span&gt;

Encourage the use of TypeScript for new code.

In JavaScript, use camelCase for variable and function names.

Favour modern JavaScript features (e.g. arrow functions, async/await) over older patterns (e.g. var, function(){}).

&lt;span class=&quot;token title important&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;###&lt;/span&gt; CSS&lt;/span&gt;

In CSS, prefer Flexbox or Grid layout over older layout techniques (e.g. float, display: table).

In CSS, prefer logical properties (e.g. margin-inline-start) over physical properties (e.g. margin-left).

&lt;span class=&quot;token title important&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;##&lt;/span&gt; Web Accessibility&lt;/span&gt;

Ensure that all markup is accessible, using semantic tags and adding additional markup to support non screen users where appropriate.

&lt;span class=&quot;token title important&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;##&lt;/span&gt; Ignore&lt;/span&gt;

The following folders contain configuration or generated code and can be ignored:

dist/
build/
out/
.vscode
.env
.git/&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is something that will need to be reviewed and honed over time.&lt;/p&gt;
&lt;p&gt;Official documentation: &lt;a href=&quot;https://docs.github.com/en/copilot/how-tos/configure-custom-instructions/add-repository-instructions&quot;&gt;Adding repository custom instructions for GitHub Copilot&lt;/a&gt;&lt;/p&gt;
</description>
      <pubDate>Sun, 21 Sep 2025 12:45:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2025/using-a-github-copilot-instructions-file/</guid>
    </item>
    <item>
      <title>Structuring web components to preserve semantics and browser features</title>
      <link>https://chrissmith.xyz/blog/2025/structuring-web-components-to-preserve-semantics-and-browser-features/</link>
      <description>&lt;p&gt;I&#39;ve been working with web components, also known as custom elements, for a while. Personally, I like to use the &lt;a href=&quot;https://stenciljs.com/&quot;&gt;Stencil.js&lt;/a&gt; library to build them as it does a nice amount of scaffolding and lets me write in JSX syntax, which I like. In short, it helps me make them faster.&lt;/p&gt;
&lt;p&gt;I like to try to be as atomic as I can with components, breaking everything down to a its smallest possible part. This makes it much easier to debug things and to replace them if needed.&lt;/p&gt;
&lt;p&gt;One of the challenges with using web components is that it can lose semantics and become less accessible. Here&#39;s a common example, a list with items, like a list of messages.&lt;/p&gt;
&lt;h2&gt;Semantic HTML&lt;/h2&gt;
&lt;p&gt;In straight HTML I&#39;d like to make the list an &lt;code&gt;&amp;lt;ol&amp;gt;&lt;/code&gt; tag as the messages are ordered by date, and then use &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; tags to hold the messages. This gives a nice semantic base and assistive technologies will be able to inform the user about the length of the list, navigate the list, etc.&lt;/p&gt;
&lt;p&gt;Using web components, I&#39;d go for &lt;code&gt;&amp;lt;message-list&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;message-item&amp;gt;&lt;/code&gt;. I could still use the &lt;code&gt;&amp;lt;ol&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; tags nested but it ends up like this, which breaks the parent-child relationship between the semantic tags and therefore loses the meaning.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;message-list&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ol&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;message-item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;...&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;message-item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;ol&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;message-list&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we drop the &lt;code&gt;&amp;lt;ol&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; we can use aria roles to replace the semantics.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;message-list&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;list&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;message-item&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;listitem&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;...&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;message-item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;message-list&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It is best practice to use semantic tags over roles. Furthermore, in this case, the aria role of &amp;quot;list&amp;quot; does not distinguish between ordered or unordered so we lose that meaning too.&lt;/p&gt;
&lt;p&gt;My solution is simply to be less atomic and to use a single web component with this structure.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;message-list&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ol&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;...&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;ol&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;message-list&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This preserves the &lt;code&gt;&amp;lt;ol&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; semantics and relationships.&lt;/p&gt;
&lt;h2&gt;Browser features vs the shadow DOM&lt;/h2&gt;
&lt;p&gt;In this same example with messages, I wanted to be able to expand each message title to show the message content. For this I included &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;summary&amp;gt;&lt;/code&gt; tags inside each &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In order to make it function as an accordion, where only one message could be expanded at a time, I used the same &lt;code&gt;name&lt;/code&gt; attribute on each &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt; tag to control this - similar to radio button groups.&lt;/p&gt;
&lt;p&gt;With separate nested web components it looks like this.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;message-list&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;message-item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;details&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;summary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;title #1&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;summary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;content&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;...&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;details&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;message-item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;message-item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;details&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;summary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;title #2&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;summary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;content&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;...&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;details&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;message-item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;message-item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;details&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;summary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;title #3&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;summary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;content&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;...&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;details&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;message-item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;message-list&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This works in the light DOM but not in the shadow DOM. If each &lt;code&gt;&amp;lt;message-item&amp;gt;&lt;/code&gt; uses the shadow DOM then the details elements are no longer aware of each other. It can be made to work via firing events on a common ancestor element but requires JavaScript so it&#39;s no longer really making use of the native browser feature.&lt;/p&gt;
&lt;p&gt;As part of this functionality to expand the items and show the message content I also wanted to animate the content expanding. We are now able to animate to values like &lt;code&gt;auto&lt;/code&gt; but it&#39;s not entirely simple. I use this CSS to achieve the animation.&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;::details-content&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;block-size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;overflow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; clip&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;transition&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; block-size 0.5s ease&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; content-visibility 0.5s ease allow-discrete&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@supports&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;interpolate-size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; allow-keywords&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token selector&quot;&gt;:root&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;interpolate-size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; allow-keywords&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token selector&quot;&gt;[open]::details-content&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;block-size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; auto&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Again, this does not work if we use the shadow DOM, only in the light DOM.&lt;/p&gt;
&lt;p&gt;Whilst using the shadow DOM brings advantages like encapsulation, it is not always compatible with browser features which rely on relationships with other DOM elements.&lt;/p&gt;
&lt;p&gt;Sometimes, simplifying our web components by using fewer components or the light DOM can actually leverage better use of the browser&#39;s native features and semantics.&lt;/p&gt;
</description>
      <pubDate>Thu, 18 Sep 2025 10:45:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2025/structuring-web-components-to-preserve-semantics-and-browser-features/</guid>
    </item>
    <item>
      <title>The evolution of software development</title>
      <link>https://chrissmith.xyz/blog/2025/the-evolution-of-software-development/</link>
      <description>&lt;p&gt;A lot of software boils down to data in, data out. We find ways of capturing data from users or services and then we expose it in reports or visualisations. I&#39;ve noticed a few shifts in the developer&#39;s role in this.&lt;/p&gt;
&lt;h2&gt;Dev makes thing&lt;/h2&gt;
&lt;p&gt;In the past, if we wanted a new web based form to capture user data, on behalf of a client, the developer would build a HTML form, based on a design spec from a product manager.&lt;/p&gt;
&lt;h2&gt;Dev makes tool&lt;/h2&gt;
&lt;p&gt;The first shift was that the developer no longer builds a form but implements a way for less technical colleagues to create their own forms without code. From the client and product management points of view, things can now move much faster as changes can be made without developers, as long as what is required is supported. So, developers don&#39;t build the thing but the tooling for others to build the thing. If more work is done by less skilled staff it saves money.&lt;/p&gt;
&lt;h2&gt;User makes thing&lt;/h2&gt;
&lt;p&gt;The second shift was that the developer still builds the tooling but now it is given directly to the client. The product people no longer make the changes, the client does it, which is even faster. The role of product management has changed so that they now support the client and manage the evolution of the tooling.&lt;/p&gt;
&lt;h2&gt;AI makes thing&lt;/h2&gt;
&lt;p&gt;Is the next shift to create tooling where the client can just use a prompt to generate the thing they need without spending the time on it?&lt;/p&gt;
</description>
      <pubDate>Mon, 09 Jun 2025 22:20:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2025/the-evolution-of-software-development/</guid>
    </item>
    <item>
      <title>Introducing RandoRacer.com</title>
      <link>https://chrissmith.xyz/blog/2025/introducing-rando-racer/</link>
      <description>&lt;p&gt;I&#39;ve built a fun little web app so thought I&#39;d share how I came up with it and how it&#39;s written.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://randoracer.com/&quot;&gt;Rando Racer&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://chrissmith.xyz/img/randoracer-screenshot.webp&quot; alt=&quot;Rando Racer screenshot showing a track with 4 lanes, bikes in each and racers called John, Paul, George and Ringo&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Origin story&lt;/h2&gt;
&lt;p&gt;The idea came from our team&#39;s morning stand-up calls. Our scrum master at the time encouraged us to take turns in running the meeting, walking through our board, checking how everybody was getting on, the usual stuff. To pick who would run the next morning&#39;s meeting we started off with nominating but then later moved to using a random picker. We started with wheelofnames.com but then people found other random pickers online. They were mostly quite bad. I felt I could do better. This was early 2024.&lt;/p&gt;
&lt;p&gt;Rather than just pick a name at random, which is very easy to program, I wanted it to be entertaining. So, I came up with the idea of a race. There would be a start and a finish and racers would move a random amount of distance forwards each turn. The concept is much like a board game with players taking turns and moving according to the roll of a die.&lt;/p&gt;
&lt;h2&gt;First version&lt;/h2&gt;
&lt;p&gt;The first version was just like this. I set each racer&#39;s score to 0 and the aim was to reach 100. Each turn their score would increase by a random amount, 1-6. The first to 100 would be the winner.&lt;/p&gt;
&lt;p&gt;I used a :bike: emoji for the racer and on each turn set its &lt;code&gt;right&lt;/code&gt; property to the score + &#39;%&#39;, so it moved from right to left. The racer CSS included a transition on the &lt;code&gt;right&lt;/code&gt; property so it moved smoothly.&lt;/p&gt;
&lt;p&gt;Finally, I added a basic form so that the user could add their own list of names that got attributed to the racers. I added the racers&#39; names just above the emoji. And that was it. All quite simple.&lt;/p&gt;
&lt;h2&gt;Taking it forward&lt;/h2&gt;
&lt;p&gt;Over time I added some enhancements. I stored the names in localStorage so that you would automatically get the last list you used on that device. I tweaked the scoring from 1-6 to a kind of Fibonacci sequence but weighted more towards 1, `[1, 1, 1, 2, 3, 5]. This made the sudden boost more impactful. I added some keyframes animation, making each bike appear to shake slightly throughout. I added a confetti effect when there was a winner, using the JSConfetti library via a CDN.&lt;/p&gt;
&lt;p&gt;The final part of this phase was to add commentary. I realised that I wanted to make the whole thing somewhat accessible, so there would need to be some kind of text description of what was happening. I felt that the easiest way to achieve this would be to update something in the DOM and use aria-live so that a screen reader user would receive updates. The frequency of updates has always been an issue but using &amp;quot;polite&amp;quot; they get updated as often as possible without any one update being critical. As I was adding this I thought I&#39;d also share it on screen to add another dimension.&lt;/p&gt;
&lt;p&gt;I had lots of other ideas for it but it was now quite limited by the way I&#39;d written it.&lt;/p&gt;
&lt;h2&gt;Second version&lt;/h2&gt;
&lt;p&gt;In early 2025 I decided to do a complete rewrite from the ground up, with the aim of making it more flexible and configurable.&lt;/p&gt;
&lt;h3&gt;Functions&lt;/h3&gt;
&lt;p&gt;The biggest change was to throw out the idea of moving X percent each turn and instead make it all function based. There would be a library of functions that would apply an effect to the racer. Some would be simple, like increase the score by 1%, others might be a big boost of 10%.&lt;/p&gt;
&lt;h3&gt;Probability&lt;/h3&gt;
&lt;p&gt;Rather than just apply a random function I also introduced the concept of probability against each so that more ordinary functions like increase the score by 1% could have a high chance of being applied whereas the more dramatic ones like the +10% would be improbable and rarely seen.&lt;/p&gt;
&lt;h3&gt;State&lt;/h3&gt;
&lt;p&gt;As well as changing the score I also brought in the concept of state. So, a racer&#39;s normal state would be &amp;quot;active&amp;quot; but they can also be other things, like &amp;quot;frozen&amp;quot;. In this case, the function would apply a state of &amp;quot;frozen&amp;quot;, which is also applied as the emoji&#39;s CSS class. The racer&#39;s appearance is changed to being completely white. Also, by wrapping the player&#39;s turn in an &lt;code&gt;if (player.state === &amp;quot;active)&lt;/code&gt; condition then they are unable to move or have any other effects applied until the state returns to &amp;quot;active&amp;quot;. The function also includes a &lt;code&gt;setTimeout()&lt;/code&gt; which resets the state and CSS class after a delay.&lt;/p&gt;
&lt;h3&gt;Toast&lt;/h3&gt;
&lt;p&gt;The original commentary was a single div with its textContent being updated. I changed this in favour of a toast message system so that messages would appear and then fade after a delay. This means that with more happening users get longer to see each message.&lt;/p&gt;
&lt;p&gt;The functions which control the players can also post messages and they can be styled, so we can have it show &amp;quot;Chris is frozen&amp;quot; with a pale blue background to stand out from the other plain white messages.&lt;/p&gt;
&lt;h2&gt;Your feedback&lt;/h2&gt;
&lt;p&gt;Give it a try and please let me know what you think. And feel free to suggest further twists and turns.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://randoracer.com/&quot;&gt;Rando Racer&lt;/a&gt;&lt;/p&gt;
</description>
      <pubDate>Sun, 08 Jun 2025 21:30:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2025/introducing-rando-racer/</guid>
    </item>
    <item>
      <title>Static sandwiches</title>
      <link>https://chrissmith.xyz/blog/2025/static-sandwiches/</link>
      <description>&lt;p&gt;It&#39;s lunchtime and you&#39;re going to a new sandwich shop. They&#39;ve got a wide choice of fillings. They have a load of sandwiches with the most popular fillings pre-made. Decisions decisions. Do you choose one of the pre-made ones and get it straight away, or ask for something different, maybe more custom and wait for it to be made for you, or do you get one of the popular options but have it made fresh?&lt;/p&gt;
&lt;p&gt;Let&#39;s now think about it from the sandwich shop owner&#39;s point of view. They don&#39;t have to offer pre-made sandwiches - they could all be made to order. Or they could only offer pre-made and customers just buy off the shelf.&lt;/p&gt;
&lt;h2&gt;Web content, please&lt;/h2&gt;
&lt;p&gt;I expect you&#39;ve already figured out where this is going. Let&#39;s substitute the sandwich shop for a web browser and the sandwiches themselves for web content. Just as the shop can offer pre-made sandwiches a website can offer static pre-compiled content that is available straight away. Alternatively, just as a customer can request a custom made sandwich meaning a longer wait time, a user can request a page with specific content, for example, a profile page for a particular person. This is dynamic and has to be compiled before it is served. It may involve fetching data from a database or API. The additional processing takes time. So, pre-compiled pages, like pre-made sandwiches, are obviously faster.&lt;/p&gt;
&lt;p&gt;As web developers, if we want to deliver content as efficiently as possible, it stands to reason that we should offer static content where possible and dynamic content where necessary. I used a profile page as an example of a dynamic page as this is a common pattern. There&#39;s a template for a personal profile and then the data for that one person is fetched and bound to it to create the finished page. But it doesn&#39;t have to work like this. The page could be pre-compiled and made into a static page, stored ready to be served up on demand. If the data changes or the template changes the pages are re-compiled, so they&#39;re always fresh and fast.&lt;/p&gt;
&lt;h2&gt;What about scalability?&lt;/h2&gt;
&lt;p&gt;As ever, there are trade offs. If you have a site with profile pages for team members and there are a only 10 then having 10 additional static pages is not a problem and probably the way to go. If, however, you&#39;re a huge platform with thousands of users then this is a lot of extra files to store, not to mention the overhead of having to re-compile all of the static pages every time the template changes.&lt;/p&gt;
&lt;h2&gt;What about caching?&lt;/h2&gt;
&lt;p&gt;Caching is essentially keeping a copy of the compiled page so that it doesn&#39;t have to be compiled again. There are 2 main types. The server, which does the compilation, can keep a copy handy, ready for the next request. The browser can keep a copy so that if we want the same again it&#39;ll be quicker. The complexity here is that, much like sandwiches, the content can become stale. Caching is a whole topic in itself. While some level of caching and periodic re-compilation is certainly useful for speeding up common requests for dynamic content, it&#39;s still not as efficient as static pages which are always fast and always fresh.&lt;/p&gt;
&lt;h2&gt;Static first&lt;/h2&gt;
&lt;p&gt;I changed my personal website from a WordPress site to an Eleventy site for these reasons. It&#39;s now all static and all my pages load pretty much instantly as there&#39;s no additional processing at the time of request - it&#39;s all been done at the time of publishing. No server side processing also means it&#39;s cheaper to host.&lt;/p&gt;
&lt;p&gt;Static pages won&#39;t work for all types of content. Sites with a lot of real time data or that need to run queries can&#39;t necessarily but sites which are document based, like a blog or a documentation site should almost certainly be static.&lt;/p&gt;
&lt;p&gt;We should look for opportunities to compile content as early as its change frequency and scale will allow.&lt;/p&gt;
</description>
      <pubDate>Sat, 07 Jun 2025 10:55:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2025/static-sandwiches/</guid>
    </item>
    <item>
      <title>Bulk deleting tweets</title>
      <link>https://chrissmith.xyz/blog/2024/bulk-deleting-tweets/</link>
      <description>&lt;p&gt;I joined twitter in 2009. Over the years I wrote over 4,000 tweets and at my peak had over 3,000 followers. I gained a lot of useful knowledge from following others, had some great interactions with people in the web and front end community and just had a lot of fun. But things change. X is not the same.&lt;/p&gt;
&lt;p&gt;I won&#39;t bore you with my reasons for now wanting out, as, if you&#39;re reading this, I&#39;m sure you&#39;re probably in a similar position or not too far away. The good news is that Mastodon has a thriving community, effectively back to the glory years of twitter.&lt;/p&gt;
&lt;h2&gt;The right way to go&lt;/h2&gt;
&lt;p&gt;I was initially just going to remove my account but having taken advice from others on Mastodon (thank you) there are risks associated with this. If I delete my account the username becomes available again and it opens the door for someone to be able to impersonate me. Whilst this seems unlikely, as I&#39;m not famous or anything, I have had a similar experience in the past with allowing a domain name to expire and somebody taking it over and benefitting from my work in building a website&#39;s reputation.&lt;/p&gt;
&lt;p&gt;So, I&#39;m going to do as others have suggested, leave my account intact but delete all the tweets. This removes my history and hopefully prevents my data from being used to train AI models, not that I can ever know or do anything about that.&lt;/p&gt;
&lt;h2&gt;Deleting the tweets&lt;/h2&gt;
&lt;p&gt;Obviously, you can just go to your Profile page and start manually deleting away. I started doing this but it didn&#39;t take me long to realise how long this was going to take. So, an automated solution was needed. There are paid services out there but it struck me as being too trivial to be worth paying for. I&#39;m quite used to using Playwright to run automated scripts on a UI in my job but even this seemed like overkill. I decided to just write a script and run it in the browser&#39;s JavaScript console.&lt;/p&gt;
&lt;h2&gt;Instructions&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Open X in Chrome&lt;/li&gt;
&lt;li&gt;Navigate to your Profile page&lt;/li&gt;
&lt;li&gt;Open the DevTools (F12)&lt;/li&gt;
&lt;li&gt;Open the Console tab&lt;/li&gt;
&lt;li&gt;Paste the script below into the console and hit Enter&lt;/li&gt;
&lt;li&gt;Leave it running...&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You should see the count of posts gradually come down at the top of the screen, though this does not refresh every time.&lt;/p&gt;
&lt;h2&gt;The script&lt;/h2&gt;
&lt;p class=&quot;codepen&quot; data-height=&quot;1100&quot; data-default-tab=&quot;js&quot; data-slug-hash=&quot;VwoOrOV&quot; data-pen-title=&quot;Bulk Delete Tweets&quot; data-user=&quot;chris22smith&quot; style=&quot;block-size: 1100px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;&quot;&gt;
  &lt;span&gt;See the Pen &lt;a href=&quot;https://codepen.io/chris22smith/pen/VwoOrOV&quot;&gt;
  Delete Tweets&lt;/a&gt; by Chris Smith (&lt;a href=&quot;https://codepen.io/chris22smith&quot;&gt;@chris22smith&lt;/a&gt;)
  on &lt;a href=&quot;https://codepen.io/&quot;&gt;CodePen&lt;/a&gt;.&lt;/span&gt;
&lt;/p&gt;
&lt;script async=&quot;&quot; src=&quot;https://cpwebassets.codepen.io/assets/embed/ei.js&quot;&gt;&lt;/script&gt;
&lt;h2&gt;The breakdown&lt;/h2&gt;
&lt;p&gt;For anyone interested, I&#39;ll explain how it works, not because you need to know but because you amy be able to write similar things to run against other web applications.&lt;/p&gt;
&lt;p&gt;The basics are to find a tweet, find the interactive elements needed and click them but there&#39;s a bit more to it.&lt;/p&gt;
&lt;h3&gt;Recursive&lt;/h3&gt;
&lt;p&gt;You can&#39;t simply use &lt;code&gt;document.querySelectorAll()&lt;/code&gt; to select all the tweets as only a small number are loaded, with more loading on scroll. So, I decided to use a recursive approach and just tackle the first tweet, then, once that has been deleted tackle the first tweet again, and so on. You&#39;ll see the &lt;code&gt;deleteFirstPost()&lt;/code&gt; function called again towards the end of itself. Handily, &lt;code&gt;document.querySelector()&lt;/code&gt; returns the first matching item.&lt;/p&gt;
&lt;h3&gt;Timeouts&lt;/h3&gt;
&lt;p&gt;There are a lot of timeouts used. From my experience working with Playwright for automated testing I&#39;ve learnt that it&#39;s important to give a web app some breathing space. Humans can only click things so fast but machines can do things instantly. Sometimes this is too fast and it can try to do something before it has rendered or is in a ready state. So, many of the interactions are wrapped in a &lt;code&gt;setTimeout()&lt;/code&gt; function with a 500 millisecond delay.&lt;/p&gt;
&lt;p&gt;The final recursive calling of the &lt;code&gt;deleteFirstPost()&lt;/code&gt; function is wrapped with a 5000 millisecond or 5 second delay. Whilst this obviously makes things quite a bit slower, waiting 5 seconds between each deletion, it&#39;s important to leave a gap. Actions like deleting posts are usually rate limited, meaning that if you try to do things at too high a frequency it is seen as suspicious and blocked. Leaving a longer gap and just leaving it running is more effective.&lt;/p&gt;
&lt;h3&gt;Selectors&lt;/h3&gt;
&lt;p&gt;The final piece to this function is using the right selectors. The HTML is div soup, layers and layers of div elements and it uses dynamic classes so they will never be guaranteed to be the same twice, so we can&#39;t really use any of that. However, it does use the &lt;code&gt;data-testid&lt;/code&gt; attribute on eahc button so we can use this.&lt;/p&gt;
&lt;p&gt;The other main selector used is the dropdown option for &amp;quot;Delete&amp;quot; or &amp;quot;Undo post&amp;quot;. The dropdown and it&#39;s children are just more divs but they ave been given accessible roles, &lt;code&gt;menu&lt;/code&gt; and &lt;code&gt;menuitem&lt;/code&gt;. The text itself is in a span inside the menu item. Luckily for us, it&#39;s always the first item we need so we can just use &lt;code&gt;document.querySelector()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Whenever I use a selector I then check if it exists, if it has found a match, before trying to use it. This makes it more robust and less likely to fail. In the case of the dropdown items I also do a quick check against the menu item text to make sure we&#39;re picking the right option. If the site was to reorder the options it would break otherwise and who know what bulk action we might be taking.&lt;/p&gt;
&lt;h3&gt;Scroll&lt;/h3&gt;
&lt;p&gt;I added a small scroll with &lt;code&gt;window.scrollBy(0, 150);&lt;/code&gt; so that it keeps slowly moving down the page with each deletion. This is just to ensure that the screen does not fill with other non tweet content like ads or recommendations on who to follow and prevent more tweets from loading up and being availbale to select.&lt;/p&gt;
&lt;h2&gt;Please share&lt;/h2&gt;
&lt;p&gt;If you found this useful please feel free to use it yourself and share with others. Thanks.&lt;/p&gt;
</description>
      <pubDate>Tue, 19 Nov 2024 17:00:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2024/bulk-deleting-tweets/</guid>
    </item>
    <item>
      <title>Simplifying dates in JavaScript</title>
      <link>https://chrissmith.xyz/blog/2024/simplifying-dates-in-javascript/</link>
      <description>&lt;p&gt;I&#39;ve always found working with dates in JavaScript to be a horrible experience but it really doesn&#39;t have to be. There&#39;s an easy way for most use cases.&lt;/p&gt;
&lt;p&gt;JavaScript has a built-in &lt;code&gt;Date&lt;/code&gt; object with its own constructor function and various methods for getting or setting different parts of the date object or formatting it in different ways. If you need to do more advanced things with manipulating dates then you&#39;ll probably have to use this but a lot of the time it&#39;s just not needed. Let&#39;s look at some of the most common use cases of working with dates and keep it as simple as possible.&lt;/p&gt;
&lt;h2&gt;Use case 1: Input a date and submit it&lt;/h2&gt;
&lt;p&gt;Let&#39;s say we&#39;ve got a form capturing personal details which includes a date of birth input. We can use a native input tag with type set to &lt;code&gt;&amp;quot;date&amp;quot;&lt;/code&gt;. This will allow typing in the user&#39;s browser locale, e.g. &lt;code&gt;dd/MM/yyyy&lt;/code&gt; format in the UK, &lt;code&gt;MM/dd/yyyy&lt;/code&gt; in the US, and probably offer a nice UI for picking a date. From the user&#39;s point of view it&#39;s all as they would expect. Under the hood, the date is captured as a string in &lt;code&gt;yyyy-MM-dd&lt;/code&gt; format. Sending this string to the server should be recognised as a date and handled appropriately. It can be stored as a string or will get cast to a &lt;code&gt;DateTime&lt;/code&gt; type.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;date&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;dob&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Use case 2: Loading a date&lt;/h2&gt;
&lt;p&gt;If we stick with the example above but now want to edit the details then first we&#39;ll need to load them. If the date was stored as a string then it will load straight in with no additional steps needed.&lt;/p&gt;
&lt;p&gt;If it was stored as a &lt;code&gt;DateTime&lt;/code&gt; type then it will also include some blank time information not needed by the input so we&#39;ll need to get rid of that. There are a few ways of doing that but my preference is to slice the string to only the characters needed. Firstly we use the &lt;code&gt;toISOString()&lt;/code&gt; date method to convert the datetime to ISO format, which starts with &lt;code&gt;yyyy-MM-dd&lt;/code&gt; then we slice the string to keep only the first 10 characters - the 4 digit year, 2 digit month and 2 digit day plus the 2 delimiting dashes.&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;input[name=dob]&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; dob
  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toISOString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;slice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Use case 3: Date comparison&lt;/h2&gt;
&lt;p&gt;If you have dates in a &lt;code&gt;yyyy-MM-dd&lt;/code&gt; string format then it&#39;s easy to compare them as they are already in alphanumeric order. So we can do things like this:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; startDate &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;input[name=start]&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; endDate &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;input[name=end]&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;startDate&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; endDate&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// tell the user that the start date can&#39;t be after the end date&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or, as another idea, we could sort a list of people by their date of birth. If we have an array called &lt;code&gt;people&lt;/code&gt; with objects containing a &lt;code&gt;dob&lt;/code&gt; property we can do this:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; peopleSortedbyDateOfBirth &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; people&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; a&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dob &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dob&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Conversions&lt;/h2&gt;
&lt;p&gt;If you need to do something that requires the Date object then it&#39;s easy to convert from &lt;code&gt;yyyy-MM-dd&lt;/code&gt; string to &lt;code&gt;Date&lt;/code&gt;. The &lt;code&gt;Date&lt;/code&gt; constructor can take the date string and convert it.&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; dateOfBirthString &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;input[name=dob]&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; dateOfBirthAsDate &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dateOfBirthString&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And, as we&#39;ve seen previously, if we have a &lt;code&gt;Date&lt;/code&gt; object we can get it back into a &lt;code&gt;yyyy-MM-dd&lt;/code&gt; string by doing this:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; dateOfBirthAsDate &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1993&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 4th Oct 1993 - the month is zero indexed&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; dateOfBirthString &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; dateOfBirthAsDate&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toISOString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;slice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you need to output a date on screen the easiest way is to use the &lt;code&gt;Intl.DateTimeFormat&lt;/code&gt; object. This allows you to set a preferred language or locale to use. Or, if you leave the locale blank it will use the browser locale, which will probably be right most of the time.&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; eventDateString &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2024-09-15&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// yyyy-MM-dd&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; eventDateAsDate &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;eventDate&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// converted&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; displayDate &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Intl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;DateTimeFormat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;en-US&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;eventDateAsDate&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 09/15/2024&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Tips&lt;/h2&gt;
&lt;p&gt;My advice would be to work with strings wherever possible. If not strings then the Date object. Keep human formatted dates like &#39;09/15/2024&#39; out of your code and convert between working and display date formats. Strings in the &lt;code&gt;yyyy-MM-dd&lt;/code&gt; format are easiest for comparison and sorting.&lt;/p&gt;
</description>
      <pubDate>Wed, 04 Sep 2024 16:15:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2024/simplifying-dates-in-javascript/</guid>
    </item>
    <item>
      <title>Replacing jQuery UI datepicker with HTML date input</title>
      <link>https://chrissmith.xyz/blog/2024/replacing-jquery-ui-datepicker-with-html-date-input/</link>
      <description>&lt;p&gt;We have an ageing web app, 10+ years, which uses jQuery UI datepicker throughout. I&#39;m currently in the process of engineering this out so that we can use native HTML input elements with type of date instead.&lt;/p&gt;
&lt;h2&gt;Why bother?&lt;/h2&gt;
&lt;p&gt;jQuery UI&#39;s datepicker dates back to a time before a native date input being a thing. At the time it was a great solution, making a nice picker UI for users. It generates a calendar view with days of the month laid out in weeks, a typical month-to-view.&lt;/p&gt;
&lt;p&gt;One of the issues with this now is that the calendar uses links for dates rather than buttons. Not only is this not very semantic and probably not very accessible but it creates the problem of links pointing to # (&lt;code&gt;href=&amp;quot;#&amp;quot;&lt;/code&gt;) and us having to use &lt;code&gt;event.preventDefault()&lt;/code&gt;. That was common practice at one time but now I think we all recognise that those links should be buttons.&lt;/p&gt;
&lt;p&gt;The other issue is just that it&#39;s an additional dependency that is not needed and is not being actively updated so it&#39;s redundant and at risk of becoming a problem in the future. If we can get rid of jQuery UI then it paves the way for getting rid of jQuery too. There could be a nice performance gain by removing the additional resource loading.&lt;/p&gt;
&lt;h2&gt;How they both work&lt;/h2&gt;
&lt;p&gt;jQuery UI datepicker works by adding the picker functionality on top of an existing text input. This raises the issue of date format. You want to read and write the format in your locale, like dd/mm/yyyy (in the UK) but want to submit the input&#39;s data as yyyy-mm-dd (ISO format). They get around this by cleverly bolting on an additional hidden input. So, you edit the visible input with the display format and it gets converted to the submission format in the hidden input.&lt;/p&gt;
&lt;p&gt;In our code there&#39;s quite a lot of format conversion going on, switching between date formats and we always have to check that data is received and sent as expected.&lt;/p&gt;
&lt;p&gt;With the native HTML date input, it&#39;s much simpler. The value is set in ISO format (yyyy-mm-dd) and the browser uses the locale to display it as appropriate. So, it comes in and goes out in the universal date format but each user only ever sees their expected format.&lt;/p&gt;
&lt;h2&gt;What&#39;s involved in switching?&lt;/h2&gt;
&lt;p&gt;Firstly, remove the datepicker function, which is where the additional functionality gets added. You should be able to find &lt;code&gt;.datepicker(&lt;/code&gt; in your code. It should now be back to a simple text input. You should still be able to use it as before but you have to type the date in the correct format, and it&#39;s not obvious what this will be, probably yyyy-mm-dd, which is odd and not really guessable for users.&lt;/p&gt;
&lt;p&gt;Change the input type from &lt;code&gt;&amp;quot;text&amp;quot;&lt;/code&gt; to &lt;code&gt;&amp;quot;date&amp;quot;&lt;/code&gt;, or add &lt;code&gt;type=&amp;quot;date&amp;quot;&lt;/code&gt; if there was no type attribute. Text is the default type so it&#39;s possible it&#39;s been omitted.&lt;/p&gt;
&lt;p&gt;If you&#39;re very lucky, that&#39;s it. It&#39;ll now automatically adapt to the user&#39;s browser locale and display dates in the correct format. It&#39;ll read in the data in the yyyy-mm-dd format and send that out.&lt;/p&gt;
&lt;h2&gt;Troubleshooting&lt;/h2&gt;
&lt;p&gt;If things are not quite as expected you&#39;ll need to look at how data is formatted coming in and how it is processed on its way out. Depending on your stack, you may need to set the format in a model or interface and check that there is no conversion when it is received after submission.&lt;/p&gt;
&lt;p&gt;You may also need to add CSS for the &lt;code&gt;input[type=date]&lt;/code&gt; if you only has &lt;code&gt;input[type=text]&lt;/code&gt; or &lt;code&gt;.datepicker&lt;/code&gt; previously.&lt;/p&gt;
&lt;h3&gt;Very specific ASP.NET MVC use case&lt;/h3&gt;
&lt;p&gt;This is beyond niche, so I won&#39;t be offended if you stop reading, but my particular code used &lt;code&gt;Html.TextBoxFor()&lt;/code&gt; syntax to add the textbox to the UI. In order to get it to read the value in the correct format I had to swap this out for &lt;code&gt;Html.EditorFor&lt;/code&gt; which allows more options on the model and then update the model to include this line:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;[DataType(DataType.Date), DisplayFormat(DataFormatString = &amp;quot;{0:yyyy-MM-dd}&amp;quot;, ApplyFormatInEditMode = true)]&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This, confusingly, doesn&#39;t actually set the display format at all but the format of the input&#39;s value string.&lt;/p&gt;
</description>
      <pubDate>Wed, 31 Jul 2024 15:45:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2024/replacing-jquery-ui-datepicker-with-html-date-input/</guid>
    </item>
    <item>
      <title>Code formatting and style guides</title>
      <link>https://chrissmith.xyz/blog/2024/code-formatting-and-style-guides/</link>
      <description>&lt;p&gt;When you have a team of developers, each with their own coding styles and preferences, how do you keep everyone aligned and your code consistent?&lt;/p&gt;
&lt;p&gt;I&#39;m talking about the little things here, like whether you use single quotes or double quotes in your JavaScript. Do you end lines in JavaScript with a semi-colon or not bother? In HTML, do you use closing tags for &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; elements or not bother? In CSS, do you order your properties alphabetically, by some other logical rule, or have no rules? Let&#39;s not get into tabs vs spaces.&lt;/p&gt;
&lt;p&gt;Without any rules in place, developers can keeping changing the coding style with each commit, so, one file could keep flipping back and forth between single and double quotes. Whilst the code still runs this does create a lot of noise in pull requests, making it much harder to see what has actually changed functionally, rather than just formatting.&lt;/p&gt;
&lt;p&gt;Some companies have a coding style guide, where they actually specify how things should be done. This is the law, this is how we do things here.&lt;/p&gt;
&lt;p&gt;This means developers actively consulting it, getting to know it and using it. This is fine with longer term employees but if there&#39;s a high turnover of developers it&#39;s not very practical.&lt;/p&gt;
&lt;h2&gt;Prettier&lt;/h2&gt;
&lt;p&gt;Our approach has been to use &lt;a href=&quot;https://prettier.io/&quot;&gt;Prettier&lt;/a&gt;, a VS Code extension which manages all of the preferences for you. Not only does it log all the rules but it enforces them and can be set to actively change the code to reflect them on file save. So, every time you open a file and save changes it implements the coding style. This does mean a lot of pull request noise the first time but then you never have to worry about it again.&lt;/p&gt;
&lt;p&gt;In terms of the actual rules, our thinking has been to just adopt Prettier&#39;s out-of-the-box default settings. We trust that the publishers will have set sensible defaults, probably the most commonly used and it also means zero maintenance of the settings. If a new dev joins we can simply get them to install the Prettier extension and it&#39;s job done. Our coding style guide is effectively now a one-liner.&lt;/p&gt;
</description>
      <pubDate>Thu, 25 Jul 2024 14:15:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2024/code-formatting-and-style-guides/</guid>
    </item>
    <item>
      <title>A dedicated pull request channel</title>
      <link>https://chrissmith.xyz/blog/2024/a-dedicated-pull-request-channel/</link>
      <description>&lt;p&gt;As often happens in tech, our company was acquired by a bigger company. Previously we were very much all Microsoft but we&#39;ve transitioned to Google. This included moving from Teams to Slack and then to Google Chat.&lt;/p&gt;
&lt;p&gt;I don&#39;t really have any strong opinion on these tools. I think they&#39;re all much the same and all do a good job. What I find more interesting is that the act of migrating from one to another means an opportunity to rethink and reorganise teams/channels/spaces. I&#39;ll just use the Slack term &amp;quot;channels&amp;quot; going forward.&lt;/p&gt;
&lt;h2&gt;Reset&lt;/h2&gt;
&lt;p&gt;In my experience, channel membership grows over time. Gradually, more and more colleagues peripheral to the core channel membership get added as the need arises but then never leave again. I&#39;ve found myself joining more and more channels where I have little to no day to day involvement. A reset is healthy.&lt;/p&gt;
&lt;p&gt;During our latest restructure I was keen to trial the idea of a dedicated channel for pull requests. This was to keep them separate from the day to day chat. My original thinking was just to reduce the noise in our chat so that if anyone asked a question it would get the attention is deserved and not get lost in the fog. It turns out it was far more useful than that.&lt;/p&gt;
&lt;h2&gt;Automated posts&lt;/h2&gt;
&lt;p&gt;We use webhooks from Azure DevOps (not Google yet) to automatically post updates to the channel. So, every time a new pull request is generated in Azure DevOps a new thread is created in the channel. Furthermore, when it is completed a reply to the same thread appears in the channel.&lt;/p&gt;
&lt;p&gt;This automation has saved us a lot of time in manually copying and pasting links to pull requests and asking our colleagues to look at them. As something is ready it posts to the channel, triggering a notification. Now, most of our pull requests are jumped on quickly, which further reduces delays.&lt;/p&gt;
</description>
      <pubDate>Thu, 25 Jul 2024 14:10:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2024/a-dedicated-pull-request-channel/</guid>
    </item>
    <item>
      <title>Converting jQuery to vanilla JavaScript with an AI assistant</title>
      <link>https://chrissmith.xyz/blog/2024/converting-jquery-to-vanilla-javascript-with-an-ai-assistant/</link>
      <description>&lt;p&gt;I&#39;m using an AI assistant to help me with some laborious code changes. As AI seems to have a bad name in developer circles, I thought I&#39;d try to give an honest appraisal of my experience and see what we can learn about using these tools.&lt;/p&gt;
&lt;h2&gt;The task&lt;/h2&gt;
&lt;p&gt;I&#39;m in the process of converting a lot of older JavaScript files, written with jQuery syntax, into vanilla JavaScript, just to remove another dependency. I&#39;d also like to refactor where posisble, updating to more modern JavaScript and improving efficiency by removing repetition, etc. Many of the script files are from 10+ years ago and written by a single developer, probably under time pressure, so there&#39;s certainly room for improvement in how the code is written.&lt;/p&gt;
&lt;h2&gt;The tool&lt;/h2&gt;
&lt;p&gt;I&#39;m using &lt;a href=&quot;https://codeium.com/&quot;&gt;Codeium&lt;/a&gt;, a free VS Code extension. On the surface it&#39;s quite like ChatGPT but is supposedly more context aware. I&#39;m using the free tier. If you have a block of code selected in the main editor window and then copy this into the chat prompt it returns a result in the chat window but offers the option of inserting it, which overwrites the code in the main window. This is a good time saver.&lt;/p&gt;
&lt;h2&gt;Prompting&lt;/h2&gt;
&lt;p&gt;I&#39;m giving the initial prompt &lt;code&gt;convert this jquery syntax to vanilla javascript&lt;/code&gt; and then pasting my block of code. Then, for the next block, I&#39;m just prompting &lt;code&gt;and this&lt;/code&gt; then pasting the next block.&lt;/p&gt;
&lt;h2&gt;Results and findings&lt;/h2&gt;
&lt;p&gt;In the main, it does a great job, exactly what you would hope for.&lt;/p&gt;
&lt;h3&gt;Selectors and attributes&lt;/h3&gt;
&lt;p&gt;It replaces &lt;code&gt;$(&amp;quot;#filter&amp;quot;)&lt;/code&gt; jQuery syntax with &lt;code&gt;document.getElementById(&amp;quot;filter&amp;quot;)&lt;/code&gt; and any other non id selectors with &lt;code&gt;document.querySelectorAll()&lt;/code&gt; and then a &lt;code&gt;.forEach()&lt;/code&gt; loop.&lt;/p&gt;
&lt;p&gt;It handles getting or setting attributes and values perfectly.&lt;/p&gt;
&lt;h3&gt;Show and hide&lt;/h3&gt;
&lt;p&gt;It replaces jQuery&#39;s &lt;code&gt;.show()&lt;/code&gt; and &lt;code&gt;.hide()&lt;/code&gt; functions with &lt;code&gt;element.style.display = &amp;quot;block&amp;quot;&lt;/code&gt; and &lt;code&gt;element.style.display = &amp;quot;none&amp;quot;&lt;/code&gt;, which is interesting. Whilst that will work a lot of the time it assumes that the displayed element has &lt;code&gt;display: block&lt;/code&gt; so it won&#39;t be quite right for elements with other initial display types. I would have thought that using the &lt;code&gt;.hidden&lt;/code&gt; property would be safer as this does not alter the display type when shown. Of course, we can tell it to do this.&lt;/p&gt;
&lt;p&gt;The other issue with &lt;code&gt;.show()&lt;/code&gt; and &lt;code&gt;.hide()&lt;/code&gt; was when it takes a value, e.g. &lt;code&gt;.show(200)&lt;/code&gt; or &lt;code&gt;.show(&amp;quot;fast&amp;quot;)&lt;/code&gt;. It doesn&#39;t seem to understand this transition duration so just omits it. As I&#39;m dealing with old code here I feel I can live with this. Ideally I&#39;d prefer to handle any animation with CSS anyway so that&#39;s another job for another day.&lt;/p&gt;
&lt;h3&gt;Requests&lt;/h3&gt;
&lt;p&gt;jQuery&#39;s ajax requests, like &lt;code&gt;$.get()&lt;/code&gt; and &lt;code&gt;$.post()&lt;/code&gt; seemed to convert well, though it did sometimes use &lt;code&gt;fetch()&lt;/code&gt; and sometimes &lt;code&gt;XMLHttpRequest&lt;/code&gt; (XHR). I had to specify that I preferred to use &lt;code&gt;fetch()&lt;/code&gt;. I also noticed that it added a &lt;code&gt;catch()&lt;/code&gt; clause, console logging the error, which was not in the original code, so it&#39;s trying to follow best practices.&lt;/p&gt;
&lt;h3&gt;Syntax preferences&lt;/h3&gt;
&lt;p&gt;There are other areas where there can be multiple ways of writing JavaScript and you have to tell it what you prefer. For example, it may mix using traditional for loops, &lt;code&gt;for (var i = 0; i &amp;lt; 10; i++)&lt;/code&gt; with &lt;code&gt;.forEach()&lt;/code&gt; or flip between if statements and ternaries. As with most LLMs I think it comes down to being detailed in the prompting or following up with subsequent prompts - it can&#39;t reasonably be expected to guess what you want. That said, I was a little disappointed that it didn&#39;t seem to remember when I had expressed preferences previously and still used alternatvie syntax.&lt;/p&gt;
&lt;h3&gt;Oddities&lt;/h3&gt;
&lt;p&gt;Everything was going well and then suddenly it replied with:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I converted the jQuery code to vanilla JavaScript. I kept the code as it is since it is already written in JavaScript.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Thanks for nothing. This was very unexpected as it had already done about 20 conversion operations successfully. It&#39;s like it forgot everything that had gone before. Perhaps this was a failing on my part as I had not given it a thumbs up for doing things correctly until this point to confirm that the results were what I had wanted. Maybe it always treats each prompt as a fresh instruction and it can always be interpreted differently. I think that it comes back to prompting. My simple prompt of &lt;code&gt;convert this jquery syntax to vanilla javascript&lt;/code&gt; was maybe not very specifically what I wanted and, technically, its response is reasonable. Maybe I need to say &lt;code&gt;rewrite this javascript to remove the dependency on jquery&lt;/code&gt;. This does seem to work consistently, so far.&lt;/p&gt;
&lt;h3&gt;Dependencies&lt;/h3&gt;
&lt;p&gt;Occasionally the code had other dependencies, like jQuery UI, and it was not able to convert this, or at least not in a way that I could be confident it would work and that it hasn&#39;t just guessed the content of the dependency. Maybe jQuery UI is so commonplace that it would know but it would need a lot of testing. These parts have been left and I will tackle them manually another time.&lt;/p&gt;
&lt;h3&gt;Scale&lt;/h3&gt;
&lt;p&gt;I started doing these code block conversions very cautiously, one function at a time, carefully checking each line, but I have grown to trust it and accept its output more readily after a quick skim. I tried feeding it more code blocks at once, like 3 functions, then 5 and it seems ok, but there is definitely a hard limit. I have one file that has over 3,000 lines and it certainly can&#39;t do that in one go. I wonder if doing more at once can lead to better context awareness and it might see more opportunities for efficiency gains. I might need to start paying to do more, which is fair enough.&lt;/p&gt;
&lt;h3&gt;Refactoring&lt;/h3&gt;
&lt;p&gt;I was also interested to see to what extent it would try to rewrite and improve upon code as well as just replace syntax. Admittedly, I&#39;ve not asked it to do this. I&#39;m just wondering if it would naturally base its code knowledge on good code or bad code, well used or cutting edge. The honest answer is... a complete mixture. It does not have a style or set preferences, which is something that really differentiates it from a human. Sometimes it will reorganise the code to avoid repetition; sometimes it won&#39;t. Sometimes it will optimise a conditional statement to give it a faster exit; sometimes it won&#39;t. It&#39;s very inconsistent. I think explicitly asking it to refactor code and seeing what it does will be a separate experiment.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In summary, I&#39;d say that there&#39;s no question that using Codeium is saving me hours of manual work. Even if some of the changes are not particularly difficult the time involved is still huge. My main takeway is that you can&#39;t expect it to work perfectly straight away. The AI needs very clear instructions and time to learn, and the human needs to invest time in learning how to use the AI tool, get the prompts right and get the best results.&lt;/p&gt;
&lt;p&gt;It&#39;s a very worthwhile investment for a larger task but for a one off conversion of one function it&#39;s probably not worth the time getting the prompting just right. You&#39;d need to be experienced with using AI tools and be an expert prompter or just get lucky to see the value.&lt;/p&gt;
</description>
      <pubDate>Fri, 19 Jul 2024 13:40:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2024/converting-jquery-to-vanilla-javascript-with-an-ai-assistant/</guid>
    </item>
    <item>
      <title>Positioning popover elements (pseudo-anchoring)</title>
      <link>https://chrissmith.xyz/blog/2024/positioning-popover-elements-pseudo-anchoring/</link>
      <description>&lt;p&gt;I&#39;ve made a number of help components over the years, typically an icon button triggering a div to appear. My approach has always been the same. Give the button &lt;code&gt;position: relative&lt;/code&gt; and then position the revealed content div using &lt;code&gt;position: absolute&lt;/code&gt;, effectively anchoring it off the button.&lt;/p&gt;
&lt;p&gt;Taking it further, I&#39;d also add a &lt;code&gt;position: fixed&lt;/code&gt; overlay layer with partial opacity above the base page with &lt;code&gt;z-index: 1&lt;/code&gt; and then put the content above that with &lt;code&gt;z-index: 2&lt;/code&gt;. It would also need a way of closing it, so adding a click event to the overlay element and also a cross icon button and close event to the content div. This would use JavaScript to return focus to the original icon button.&lt;/p&gt;
&lt;p&gt;There are loads of examples of this if you search &amp;quot;tooltip&amp;quot;, many claiming to be CSS only solutions, but I would suspect a lot of them don&#39;t manage the focus properly for screen reader use or keyboard navigation.&lt;/p&gt;
&lt;h2&gt;Welcome popover&lt;/h2&gt;
&lt;p&gt;The new popover attribute takes away a lot of this extra work. It takes care of the layers, interactivity and focus management. But not the positioning.&lt;/p&gt;
&lt;p&gt;Read more about &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Popover_API&quot;&gt;popover&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The new popover element is placed in the DOM&#39;s &lt;code&gt;top-layer&lt;/code&gt; on top of all other page content so it has no awareness of the original triggering button and its positioning. This has to be set with JavaScript.&lt;/p&gt;
&lt;p&gt;The relationship between the popover and trigger elements means that the content div will be shown and hidden automatically without us having to add any event handling.&lt;/p&gt;
&lt;h2&gt;Handling positioning&lt;/h2&gt;
&lt;p&gt;When the icon button is clicked we can fire a function to handle positioning like this:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// define the content div, create or reference a template&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; helpContent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createElement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;div&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;handlePopoverPositioning&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; scrollY &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;round&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;scrollY&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; helpButtonRect &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;target&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getBoundingClientRect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  helpContent&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;insetBlockStart &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;helpButtonRect&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;top &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; scrollY &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;px&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  helpContent&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;insetInlineStart &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;helpButtonRect&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;left &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;px&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We get the &lt;code&gt;scrollY&lt;/code&gt; value to see how far the user has scrolled the page vertically as this will affect the placement of the popover. This can be a decimal in modern browsers so I&#39;ve chosen to round it to keep things simpler but there&#39;s probably no need. We get the bounding client rectangle of the help button so that we&#39;ve got access to its dimensions and positioning. We can then set the positioning of the help content using the &lt;code&gt;insetBlockStart&lt;/code&gt; (top) and &lt;code&gt;insetInlineStart&lt;/code&gt; (left) properties. The vertical positioning has to factor in the &lt;code&gt;scrollY&lt;/code&gt; value. Finally numbers can be added or subtracted to offset the top left position of the content div.&lt;/p&gt;
&lt;h2&gt;Anchoring&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.chrome.com/blog/anchor-positioning-api&quot;&gt;CSS anchor positioning&lt;/a&gt; will make this easier and take away the need for JavaScript here by defining an anchor element, the icon button, in CSS. At the time of writing this is only available in Chromium browsers, so I can&#39;t use it yet.&lt;/p&gt;
&lt;p&gt;Hopefully the function above or something similar will help tide you over until anchoring fully arrives.&lt;/p&gt;
</description>
      <pubDate>Wed, 19 Jun 2024 16:55:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2024/positioning-popover-elements-pseudo-anchoring/</guid>
    </item>
    <item>
      <title>The connection between communication languages and programming languages</title>
      <link>https://chrissmith.xyz/blog/2024/the-connection-between-communication-languages-and-programming-languages/</link>
      <description>&lt;p&gt;I&#39;ve been working as a web developer since late 1999. A fair while. I&#39;m completely self-taught from books, courses, videos, working with great people and just doing the job.&lt;/p&gt;
&lt;p&gt;My background is not in Computer Science or anything that stands out as being technical at all. I&#39;ve got an Arts degree in French and Italian. However, I think that there is a strong connection between communication languages and programming languages that is not widely recognised.&lt;/p&gt;
&lt;h2&gt;Are &amp;quot;the arts&amp;quot; really that artsy?&lt;/h2&gt;
&lt;p&gt;When I was at school and university studying modern languages, there were defintiely different types of students. There were those who were confident speaking, unafraid to make mistakes, strong communicators, typically not so concerned with accuracy and so maybe weaker at translation or written work. Then there were those, like me, who were less confident speaking, always worrying about getting things wrong, wanting everything to be perfect but good at translation and writing which is less pressurised and more considered. Of course, there were also a few who could do it all. Pah!&lt;/p&gt;
&lt;p&gt;I think the type of linguists who like learning grammar, syntax, rules and quirks of languages would make good programmers. They&#39;re what I would term &amp;quot;technical linguists&amp;quot;. It&#39;s very much the same skill set. It&#39;s all about logical problem solving, operating within a set of rules, learning the exceptions, research, ongoing self-teaching.&lt;/p&gt;
&lt;p&gt;Once you know one communication language then learning another becomes much easier - you know the grammatical terminology and the concepts - it&#39;s just learning the new parts. It&#39;s exactly the same with programming. Once you know what a loop is, or a class, then you can use that knowledge again.&lt;/p&gt;
&lt;p&gt;I think there&#39;s also a comparison to be made with musicians. While regarded as an &amp;quot;arts&amp;quot; or &amp;quot;humanities&amp;quot; subject, there are two sides to it - the creative and performance side and the technical side.&lt;/p&gt;
&lt;h2&gt;Recognising the hidden technicians&lt;/h2&gt;
&lt;p&gt;I think employers in tech can be too quick to discount those with an &amp;quot;arts&amp;quot; background. They may actually be very technically minded and you may even get a bit of the creative side thrown into the bargain for free.&lt;/p&gt;
&lt;h2&gt;Broad and shallow or narrow and deep&lt;/h2&gt;
&lt;p&gt;When I was younger I was very into learning languages. At school I studied French, German, Russian, Latin and ancient Greek. At uni I did Italian. Later in life I&#39;ve learnt some Spanish and Welsh. So, if you include English and the dead ones, that&#39;s 9 in all. Maybe &amp;quot;obsessed&amp;quot; wouldn&#39;t be overstating it.&lt;/p&gt;
&lt;p&gt;Conversely, when it has come to programming languages, I&#39;ve done bits of other languages like Visual Basic, C# and SQL but am pretty much a core platform, front end, HTML, CSS and JavaScript guy. Do frameworks count? It&#39;s certainly more syntax to learn but I&#39;d say that&#39;s more like an off-shoot, like learning business French. It&#39;s a specialism rather than a core skill.&lt;/p&gt;
&lt;p&gt;My experience in both arenas has been that going deep in one language is more beneficial than skimming the surface of lots. Once you have a deeper knowledge of one then applying that knowledge to another is much easier. It&#39;s also much more satisfying as you can do more. I wish someone had told me that at school.&lt;/p&gt;
&lt;p&gt;I would definitely advise anyone new to tech to stop trying to learn every new shiny thing that comes along and to focus on getting a deeper understanding of the main core technologies. They have more longevity and will ultimately be more satisfying.&lt;/p&gt;
</description>
      <pubDate>Wed, 19 Jun 2024 11:45:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2024/the-connection-between-communication-languages-and-programming-languages/</guid>
    </item>
    <item>
      <title>Making a selected value readable when the text is long</title>
      <link>https://chrissmith.xyz/blog/2024/making-a-selected-value-readable-when-the-text-is-long/</link>
      <description>&lt;p&gt;If a select list has options with long text, we can see the text when the options are all shown but not after the selection has been made. Let&#39;s dig into it and look at possible solutions. It&#39;s not too hard but there&#39;s no simple one-size-fits-all answer.&lt;/p&gt;
&lt;p class=&quot;codepen&quot; data-height=&quot;500&quot; data-default-tab=&quot;result&quot; data-slug-hash=&quot;oNRwyEZ&quot; data-pen-title=&quot;Make selected value readable #3 Show full text on hover&quot; data-user=&quot;chris22smith&quot; style=&quot;height: 500px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;&quot;&gt;
  &lt;span&gt;See the Pen &lt;a href=&quot;https://codepen.io/chris22smith/pen/oNRwyEZ&quot;&gt;
  Make selected value readable #3 Show full text on hover&lt;/a&gt; by Chris Smith (&lt;a href=&quot;https://codepen.io/chris22smith&quot;&gt;@chris22smith&lt;/a&gt;)
  on &lt;a href=&quot;https://codepen.io/&quot;&gt;CodePen&lt;/a&gt;.&lt;/span&gt;
&lt;/p&gt;
&lt;h2&gt;The problem&lt;/h2&gt;
&lt;p&gt;The native HTML Select element has two states, &amp;quot;open&amp;quot; showing the options and &amp;quot;closed&amp;quot; showing just its value, the selected option.&lt;/p&gt;
&lt;h3&gt;Open&lt;/h3&gt;
&lt;p&gt;In its open or expanded state the user is able to read the option text in full, even if very long. On some devices (typically desktop) the containing box showing the options expands to the width of its contents. If the text width is greater than the device width then it will get cut off but it&#39;s improbable that anyone would be writing this much in an option. On other devices (typically mobile) the text is allowed to wrap so is always readable in full.&lt;/p&gt;
&lt;h3&gt;Closed&lt;/h3&gt;
&lt;p&gt;In its closed or collapsed state the text is contained within the Select element and only the portion of the text that fits the element&#39;s width is displayed, the rest is cut off.&lt;/p&gt;
&lt;p&gt;This is not a problem for screen reader users as the text is read in full. It&#39;s a screen display issue.&lt;/p&gt;
&lt;p&gt;If the user needs to read the full text they are able to open the Select and view the selected option with full text again but this is not possible when the element is read-only or disabled.&lt;/p&gt;
&lt;h2&gt;Solutions&lt;/h2&gt;
&lt;p&gt;There are a few possible solutions. Which one works better will depend on your feature support and design.&lt;/p&gt;
&lt;h3&gt;#1 Allow wrapping&lt;/h3&gt;
&lt;p&gt;We can change the appearance of the select so that its text is allowed to wrap. This solution is CSS only and doesn&#39;t require any JavaScript.&lt;/p&gt;
&lt;p class=&quot;codepen&quot; data-height=&quot;500&quot; data-default-tab=&quot;result&quot; data-slug-hash=&quot;rNgwJVE&quot; data-pen-title=&quot;Make selected value readable #1 Allow wrapping&quot; data-user=&quot;chris22smith&quot; style=&quot;height: 500px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;&quot;&gt;
  &lt;span&gt;See the Pen &lt;a href=&quot;https://codepen.io/chris22smith/pen/rNgwJVE&quot;&gt;
  Make selected value readable #1 Allow wrapping&lt;/a&gt; by Chris Smith (&lt;a href=&quot;https://codepen.io/chris22smith&quot;&gt;@chris22smith&lt;/a&gt;)
  on &lt;a href=&quot;https://codepen.io/&quot;&gt;CodePen&lt;/a&gt;.&lt;/span&gt;
&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;select&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;appearance&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; none&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; block&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;max-width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 100%&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;white-space&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; wrap&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;First we add &lt;code&gt;appearance: none&lt;/code&gt; to remove the default browser agent styling. Unfortunately this also loses the down arrow or caret so we would need to put that back in with CSS. Changing the appearance of the select element does not affect the appearance of the child options.&lt;/p&gt;
&lt;p&gt;Adding &lt;code&gt;display: block&lt;/code&gt; and &lt;code&gt;max-width: 100%&lt;/code&gt; ensures that the height can vary but the width is constrained so it scales vertically. Finally, adding &lt;code&gt;white-space: wrap&lt;/code&gt; allows the text to wrap onto a new line as needed.&lt;/p&gt;
&lt;p&gt;This ensures that we can always read the selected text. The possible down side is that the select can now have variable height depending on how many lines of text there are, which may cause alignment issues and layout shift. It&#39;s generally good practice with forms to stack the controls so this may not be a problem but if you were to use this select in a header with fixed height then it would not work.&lt;/p&gt;
&lt;h3&gt;#2 Show the selected option in a separate element&lt;/h3&gt;
&lt;p&gt;We can stop trying to show the selected value text in the select element and show it in another element instead. We use CSS to make the select so small it doesn&#39;t show the text and then use JavaScript to copy its value to another element.&lt;/p&gt;
&lt;p class=&quot;codepen&quot; data-height=&quot;500&quot; data-default-tab=&quot;result&quot; data-slug-hash=&quot;wvbempv&quot; data-pen-title=&quot;Make selected value readable #2 Show in a separate element&quot; data-user=&quot;chris22smith&quot; style=&quot;height: 500px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;&quot;&gt;
  &lt;span&gt;See the Pen &lt;a href=&quot;https://codepen.io/chris22smith/pen/wvbempv&quot;&gt;
  Make selected value readable #2 Show in a separate element&lt;/a&gt; by Chris Smith (&lt;a href=&quot;https://codepen.io/chris22smith&quot;&gt;@chris22smith&lt;/a&gt;)
  on &lt;a href=&quot;https://codepen.io/&quot;&gt;CodePen&lt;/a&gt;.&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;We can make the select tiny, appearing more like a button, like this:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;select&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;max-width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1rem&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0 0.5rem&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This select button can then sit on its own or along side the label.&lt;/p&gt;
&lt;p&gt;It may be preferable to use &lt;code&gt;appearance: none&lt;/code&gt; and set everything expicitly for greater cross-browser consistency and to prevent any unexpected results as the default agent&#39;s appearance may change slightly over time.&lt;/p&gt;
&lt;p&gt;We add an output element immediately after the select and use JavaScript to set its value.&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; selects &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;querySelectorAll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;select&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;setOutputValue&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; output &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;target&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;nextElementSibling&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;output &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; output&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;tagName &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;OUTPUT&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    output&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;target&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

selects&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  s&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;change&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setOutputValue&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; output &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; s&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;nextElementSibling&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;output &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; output&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;tagName &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;OUTPUT&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    output&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; s&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The possible down side with this solution is that the pattern is unfamiliar. It may not be immediately obvious how it works. The output is also of variable height so may cause alignment issues or layout shifts.&lt;/p&gt;
&lt;h3&gt;#3 Show the full text on hover&lt;/h3&gt;
&lt;p&gt;This is very similar to the previous solution in that we create a separate output element to show the full text but this time we only show it when the select element is hovered.&lt;/p&gt;
&lt;p class=&quot;codepen&quot; data-height=&quot;500&quot; data-default-tab=&quot;result&quot; data-slug-hash=&quot;gOJRzeL&quot; data-pen-title=&quot;Make selected value readable #3 Show full text on hover&quot; data-user=&quot;chris22smith&quot; style=&quot;height: 500px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;&quot;&gt;
  &lt;span&gt;See the Pen &lt;a href=&quot;https://codepen.io/chris22smith/pen/gOJRzeL&quot;&gt;
  Make selected value readable #3 Show full text on hover&lt;/a&gt; by Chris Smith (&lt;a href=&quot;https://codepen.io/chris22smith&quot;&gt;@chris22smith&lt;/a&gt;)
  on &lt;a href=&quot;https://codepen.io/&quot;&gt;CodePen&lt;/a&gt;.&lt;/span&gt;
&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;form&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  ...
  &lt;span class=&quot;token property&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; relative&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token selector&quot;&gt;output&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #fff&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;border&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; solid thin currentcolor&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;box-sizing&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; border-box&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; none&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; smaller&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;inset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; auto 1rem&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; .5rem&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;pointer-events&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; none&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; absolute&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;translate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;.5rem&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; -3rem&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;z-index&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token selector&quot;&gt;select:hover + output&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; block&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The form or a container needs to have positioning set. The output is positioned using &lt;code&gt;position: absolute&lt;/code&gt;, &lt;code&gt;inset&lt;/code&gt;, &lt;code&gt;transform&lt;/code&gt; and &lt;code&gt;z-index&lt;/code&gt; and hidden by default. It is then displayed when the select is hovered. Adding &lt;code&gt;pointer-events: none&lt;/code&gt; ensures that hovering the output does not interfere with the hovering of the select.&lt;/p&gt;
&lt;p&gt;The down side here is that not all devices support hover. So, it can&#39;t be relied upon but can be a nice enhancement for devices that do.&lt;/p&gt;
&lt;script async=&quot;&quot; src=&quot;https://cpwebassets.codepen.io/assets/embed/ei.js&quot;&gt;&lt;/script&gt;
</description>
      <pubDate>Thu, 06 Jun 2024 16:15:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2024/making-a-selected-value-readable-when-the-text-is-long/</guid>
    </item>
    <item>
      <title>When should we use components and when should we just use HTML?</title>
      <link>https://chrissmith.xyz/blog/2024/when-should-we-use-components-and-when-should-we-just-use-html/</link>
      <description>&lt;p&gt;A lot of UI frameworks or design systems include a component library. This is a series of components that can be dropped into a page to add functionality.&lt;/p&gt;
&lt;p&gt;Sometimes these components are like HTML tags that don&#39;t exist yet, e.g. a card, or they add functionality easily without having to write JavaScript, e.g. a number formatter.&lt;/p&gt;
&lt;p&gt;There are some components that don&#39;t really seem to add any new functionality but just control styling or the arrangement of inner tags. For example, most component libraries have their own button, which is a standard native HTML button but wrapped in another element, basically a fancy named span. What are the pros and cons of doing this and what are the alternatives? Let&#39;s assume we&#39;re adding the custom element &lt;code&gt;&amp;lt;my-button&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Pros of using components&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;It can come pre-styled. Styling can be baked into the component so either we don&#39;t have to think about styling or we have a base style to build upon.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It can provide some structure to the inner HTML. If we want our button to optionally have an icon, we can control that it is inserted in the correct position, before or after any text with the right spacing.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;We can ensure that the markup is semantically correct and accessible.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If we want to, we can lock down the styling so that it cannot be overidden. If we use the shadow DOM we can dictate how it looks and that&#39;s how it looks.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It&#39;s easier for a developer to pick up and use, not having to worry about precise internal markup and styling. It&#39;s just &lt;code&gt;&amp;lt;my-button&amp;gt;&lt;/code&gt; plus a few attributes.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If we need to change a component&#39;s markup or styling we can do it once and it will update everywhere.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Cons of using components&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;We may be introducing JavaScript and additional complexity where simply writing HTML and CSS would do.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It needs JavaScript to work at all. So the markup can&#39;t be used in a context that does not have JavaScript, like HTML email, whereas straight HTML is much more resilient. The exception to this is if the component auther has added appropriate fallback markup between the tags.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It&#39;s slower. Probably not by much but it&#39;s more files to transfer, more script to run. If you handle all page elements in this way it will start to add up.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If you use a framework it will update at some point and there will be maintenance associated with it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Updating a component can have unexpected knock-on effects if we&#39;re not aware of everywhere that it is used. Whilst not repeating code is generally good, reuse means more testing when we make changes.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Alternatives to components&lt;/h2&gt;
&lt;p&gt;For a simple component like this button example, we could simply use a documentation site or style guide, documenting what HTML and CSS to use.&lt;/p&gt;
&lt;p&gt;We could make code snippets available including the full feature set, e.g. icons before and after button text, and the developer can simply copy the full markup removing the parts that are not needed.&lt;/p&gt;
&lt;p&gt;Probably not a very popular opinion right now but AI tools like GitHub Copilot can help add the right markup. If a similar block has been used before it can be context aware and keep things consistent with other code in your codebase.&lt;/p&gt;
&lt;h2&gt;When to use components&lt;/h2&gt;
&lt;p&gt;There no right or wrong answer here. There are a few considerations.&lt;/p&gt;
&lt;p&gt;It&#39;s down to the nature of the project, how much reusability and change we expect and how much we value developer experience compared to user experience.&lt;/p&gt;
&lt;p&gt;There&#39;s nothing wrong with using components for consistency and ease of development but we need to be wary not to constantly over-engineer very simple pages that could just be HTML.&lt;/p&gt;
&lt;p&gt;Are the people writing the frontend UI frontend developers who are comfortable writing HTML and CSS, or are they more backend or full-stackers who would prefer picking elements from an existing library?&lt;/p&gt;
&lt;p&gt;Do the page elements require lots of JavaScript to function? If there is no HTML only option this may sway our decision. An encapulated component may be preferable to separate JavaScript which adds functionality.&lt;/p&gt;
</description>
      <pubDate>Wed, 22 May 2024 16:30:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2024/when-should-we-use-components-and-when-should-we-just-use-html/</guid>
    </item>
    <item>
      <title>The development burden of user choice</title>
      <link>https://chrissmith.xyz/blog/2024/the-development-burden-of-user-choice/</link>
      <description>&lt;p&gt;When developing a site or app there&#39;s often a temptation to give the user a choice, to make something configurable to their preferences. Here are some common examples. Light and dark modes, choosing text sizing or spacing (compact vs expanded), different layouts like a stacked list vs cards.&lt;/p&gt;
&lt;p&gt;It seems like a nice idea to give the user more choice, let them use it how they prefer, but, in reality, it&#39;s not always a good thing.&lt;/p&gt;
&lt;h2&gt;Maintenance multiplied&lt;/h2&gt;
&lt;p&gt;Let&#39;s suppose we have light and dark modes. Every time we add a new feature it now needs to be tested in both modes, so that&#39;s 2x testing. If we also have a choice of list or cards, that now needs testing both modes and both layouts, 4x testing. You can see where this is going. Each choice or configurable element is introducing more risk and more development work and it multiplies.&lt;/p&gt;
&lt;p&gt;If you give a choice of a list or cards, every change you make to an item has to be made in both layouts. That&#39;s double the design, double the coding, double the testing.&lt;/p&gt;
&lt;p&gt;From a user&#39;s point of view, they will likely make a UI choice and then stick with that choice forever, so they&#39;re no longer appreciating the benefit of the feature even though it is still generating ongoing work for the development team.&lt;/p&gt;
&lt;p&gt;What was a &amp;quot;nice to have&amp;quot; feature can be quietly adding more and more maintenance work in the background.&lt;/p&gt;
&lt;p&gt;I&#39;ve fallen foul of this a few times. In my eagerness to please users and create a configurable UI, I&#39;ve given myself problems further down the line. I&#39;ve learnt the hard way that any user UI choice needs to be considered very carefully before being added.&lt;/p&gt;
&lt;h2&gt;Users adapt&lt;/h2&gt;
&lt;p&gt;The reality is that users don&#39;t really appreciate the choice as much as you think they might. If you don&#39;t offer light and dark modes then they will use what they&#39;re given and probably won&#39;t even question it.&lt;/p&gt;
&lt;p&gt;If you change your site design from having a horizontal navigation along the top to a vertical navigation down the side then just be brave and make the change. Don&#39;t try to give them the choice for a while to soften the blow. Removing choice later is worse than just changing things. They will adapt quickly and any negativity about the change will be forgotten within a very short time frame.&lt;/p&gt;
</description>
      <pubDate>Tue, 02 Apr 2024 11:30:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2024/the-development-burden-of-user-choice/</guid>
    </item>
    <item>
      <title>Not enough or too much data</title>
      <link>https://chrissmith.xyz/blog/2024/not-enough-or-too-much-data/</link>
      <description>&lt;p&gt;One of the most common tasks in front end development is requesting data from an endpoint with JavaScript and then using that data to create items in the HTML. A designer will typically think about how the data is presented as cards or list items. A developer will think about iterating through an object array and binding its properties.&lt;/p&gt;
&lt;p&gt;This is the happy path where we have a nice amount of data to work with but what about the other cases where we don&#39;t have any data or we have more than we can handle? We need to design for these scenarios too.&lt;/p&gt;
&lt;h2&gt;No data&lt;/h2&gt;
&lt;p&gt;There are 2 different types of no data. The first is where we successfully hit our endpoint and get a valid response of no data, typically getting back an empty array. This is the empty state and would typically be the starting point in a lot of apps. You start off with nothing before creating items.&lt;/p&gt;
&lt;p&gt;The other is where the network request fails and we&#39;re not able to get any data or even know if there is any data to get. This is the error state and needs to be handled.&lt;/p&gt;
&lt;h3&gt;Empty state&lt;/h3&gt;
&lt;p&gt;If there are no items to display we need to explain that to users in a message and maybe prompt them to create their first item. It&#39;s much better to handle this properly than just leave a blank space where the items would be. This may leave users wondering if it&#39;s just slow to load or broken.&lt;/p&gt;
&lt;p&gt;If you&#39;re using state, like in React, it&#39;s important to set your initial state value to something different to when no data is returned. For example, you might set the initial state to undefined but an empty array when there&#39;s no data returned. This difference allows you to handle the display logic in the UI and show the relevant content.&lt;/p&gt;
&lt;h3&gt;Error state&lt;/h3&gt;
&lt;p&gt;When there&#39;s an error we need to handle it and let the user know. Leaving a blank space and leaving the user in doubt is not helpful. The important thing is to be clear about what has happened and try to provide useful information and, if possible, something to try to resolve the issue. We can use the error code to try to point towards the nature of the problem - not found, permissions, server error. Is there anything they can try now, e.g. logging in again, refreshing or is it a network issue that might mean trying again in a while. Anything we can give is better than silence.&lt;/p&gt;
&lt;p&gt;With state, it might be worth setting the value to null in this scenario, or possibly passing the error details in so they can be used in the UI.&lt;/p&gt;
&lt;h2&gt;Too much data (excess)&lt;/h2&gt;
&lt;p&gt;The opposite of getting no data is getting loads of data and struggling to handle it, either in terms of memory or processing or just it being too much for a user to practically work with. There needs to be a strategy for managing this and sensible limits put in place for how much is downloaded and displayed. It&#39;s often better to bring back less data and keep it fast rather than keep the user waiting.&lt;/p&gt;
&lt;p&gt;Strategies for handling large volumes of data include paging, windowing and filtering.&lt;/p&gt;
&lt;h2&gt;Design for all states&lt;/h2&gt;
&lt;p&gt;So, when you think about bringing in data, think about these 4 scenarios:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;data&lt;/li&gt;
&lt;li&gt;empty&lt;/li&gt;
&lt;li&gt;error&lt;/li&gt;
&lt;li&gt;excess&lt;/li&gt;
&lt;/ul&gt;
</description>
      <pubDate>Thu, 21 Mar 2024 16:30:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2024/not-enough-or-too-much-data/</guid>
    </item>
    <item>
      <title>Please stop using flags to represent languages</title>
      <link>https://chrissmith.xyz/blog/2024/please-stop-using-flags-to-represent-languages/</link>
      <description>&lt;p&gt;Yeah, please stop doing that. Stop it. Stop. If you want to know why you should stop it then read on.&lt;/p&gt;
&lt;h2&gt;The problem&lt;/h2&gt;
&lt;p&gt;It&#39;s really quite simple. What do flags represent? Yes, countries. Are countries and languages the same? Sometimes but often not. It&#39;s not a one to one relationship. A country can use multiple languages, like English and French in Canada, and multiple countries can use one language, like German in Germany, Austria and Switzerland. So, it&#39;s a many to many relationship.&lt;/p&gt;
&lt;p&gt;If you&#39;re a company in Canada and want to show a flag for the English and French languages, what do you show? The Canadian flag doesn&#39;t help. It doesn&#39;t really make sense to show the flag of France for French but is inappropriate to show the British or American flag for English. Canadians don&#39;t consider themselves a different nationality because they use a certain language.&lt;/p&gt;
&lt;p&gt;If you&#39;re a website user in Austria and want to view the content in German, you don&#39;t want to select the German flag. You&#39;d probably understand what you need to do but it&#39;s not ideal.&lt;/p&gt;
&lt;h2&gt;The solution&lt;/h2&gt;
&lt;p&gt;The best option is to display the languages in text in their native language so that the user can always recognise their own language, like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Deutsch&lt;/li&gt;
&lt;li&gt;English&lt;/li&gt;
&lt;li&gt;español&lt;/li&gt;
&lt;li&gt;français&lt;/li&gt;
&lt;li&gt;Português&lt;/li&gt;
&lt;li&gt;普通话&lt;/li&gt;
&lt;li&gt;Русский&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With this in mind, don&#39;t hide it behind a label that says &amp;quot;Choose language&amp;quot;, just display the selected or default language and possibly add a globe icon to convey the idea of language or culture.&lt;/p&gt;
&lt;h2&gt;Same language, different culture&lt;/h2&gt;
&lt;p&gt;If you use a language picker then consider broadening it out to provide more cultural options. Rather than just offering English you could offer English (UK) and English (USA), or français (France) and français (Canada). By capturing the preferred culture as well as language you can make the best use of the JavaScript &lt;code&gt;Intl&lt;/code&gt; namespace and present details like thousand separators or date format as the user would expect. You know whether they&#39;re more likely to prefer data presented in the Imperial or Metric system. It opens up many options for greater personalisation and a better experience.&lt;/p&gt;
</description>
      <pubDate>Tue, 05 Mar 2024 16:05:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2024/please-stop-using-flags-to-represent-languages/</guid>
    </item>
    <item>
      <title>Why should we care about Web Accessibility?</title>
      <link>https://chrissmith.xyz/blog/2024/why-should-we-care-about-web-accessibility/</link>
      <description>&lt;p&gt;In a nutshell, taking care of web accessibility makes our apps...&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;available to everybody&lt;/li&gt;
&lt;li&gt;easier to use&lt;/li&gt;
&lt;li&gt;easier to test&lt;/li&gt;
&lt;li&gt;easier to sell&lt;/li&gt;
&lt;li&gt;safe from negative publicity and lawsuits&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Available to everybody&lt;/h2&gt;
&lt;p&gt;There is a proportion of the population who have disabilities or impairments that mean they cannot use the web in the same way as most people.&lt;/p&gt;
&lt;p&gt;There is a wide range of visual impairments that can affect users, including things like sensitivity to motion, colour blindness or blurred vision.&lt;/p&gt;
&lt;p&gt;Some users cannot see at all. Does not being able to see the screen mean you can&#39;t access its content or interact with it? It shouldn&#39;t. Assistive technology, in particular screen reader software can read aloud the contents of a page, reading text and annoucing interactive features. It can also handle advanced navigation, describing images or diagrams and keeping up with live changes.&lt;/p&gt;
&lt;p&gt;Some users have difficulty with fine motor skills, making it difficult for them to use a pointing device like a mouse. They rely on using a keyboard or other form of input.&lt;/p&gt;
&lt;p&gt;If we&#39;ve done our job properly and built things in an accessible way then all of these problems are mitigated and our products can be used by everyone.&lt;/p&gt;
&lt;p&gt;It&#39;s obvious that from a moral perspective this is the right thing to do and something that we would all want to do and be proud that we do. However, in the day to day reality of business, with lots of conflicting priorities, this area can&#39;t always compete with the bigger earners so here are some other reasons to care.&lt;/p&gt;
&lt;h2&gt;Easier to use&lt;/h2&gt;
&lt;p&gt;There&#39;s a reason I didn&#39;t quote numbers at you for people with disabilities or impairments. That&#39;s because these things actually affect all of us to some degree. Small print is hard to read. So is pale grey text on a white background. That&#39;s not an impairment, that&#39;s a poor design choice. If you find yourself leaning in to your screen to read something or having to use your little finger to touch something, that&#39;s a web accessibility failure, and a usability failure, which means a poor user experience. If we want our users to love our products and recommend them to others we need to get this stuff right.&lt;/p&gt;
&lt;h2&gt;Easier to test&lt;/h2&gt;
&lt;p&gt;This point is rarely spoken about but having accessible content can make automated testing much easier. If you think about it, supporting screen reader software and running automated tests are both about a machine being able to read your page and then take actions or provide feedback. It&#39;s about the page elements being described in a way that does not solely rely on them being seen. As an example, if a chart has values in text, a screen reader can read them and an automated test can check them, whereas if they&#39;re part of a generated image then they&#39;re only available to those who can see them.&lt;/p&gt;
&lt;h2&gt;Easier to sell&lt;/h2&gt;
&lt;p&gt;I very much doubt that web accessibility is at the forefront of anyone&#39;s mind when deciding whether or not to buy software but it can certainly be a factor.&lt;/p&gt;
&lt;p&gt;For any publicly funded project it will be a clear selling point, as it&#39;s a non-negotiable requirement.&lt;/p&gt;
&lt;p&gt;For private companies, it often comes up as something that is required when getting into the finer details of contract agreements, usually in the form of proving how web accessibility standards are being met. If you have not been giving this area due attention, this can be very difficult to find a way around. Auditing software makes it very easy to expose a product that is not sufficiently accessible.&lt;/p&gt;
&lt;h2&gt;Safe from negative publicity and lawsuits&lt;/h2&gt;
&lt;p&gt;I suppose that after all the carrots, this is the stick. If we don&#39;t make an effort in this area then we&#39;re exposed to negative comments, bad PR, boycotts and even legal action.&lt;/p&gt;
&lt;p&gt;It is still relatively rare but there have been anti-discrimination cases brought against websites for failing to serve disabled users and the amounts of money involved are frightening.&lt;/p&gt;
&lt;p&gt;Even if things are not fully accessible it&#39;s defintely worth having a plan in place to demonstrate positive intent and a pathway to making it accessible in the near future.&lt;/p&gt;
</description>
      <pubDate>Fri, 26 Jan 2024 16:45:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2024/why-should-we-care-about-web-accessibility/</guid>
    </item>
    <item>
      <title>Learning TypeScript</title>
      <link>https://chrissmith.xyz/blog/2024/learning-typescript/</link>
      <description>&lt;p&gt;I&#39;ve started learning TypeScript properly. After a few years of knowing bits and mostly just writing JavaScript in .ts files I decided to make the effort to understand it.&lt;/p&gt;
&lt;p&gt;A bit like a linting tool, the whole point is that it warns you when you do things wrong or expose yourself to potential problems. When you don&#39;t understand why you&#39;re being told off, it can get frustrating, and I&#39;d reached a point where it felt like more of a hindrance than a help.&lt;/p&gt;
&lt;p&gt;I think I had made some assumptions about type checking, thinking it was mostly knowing if things were a string, number or boolean, and I couldn&#39;t really see how this would be that much of an issue. In truth, that part is quite straightforward.&lt;/p&gt;
&lt;p&gt;The real value comes from picking up when things can be null or undefined. For example, if you use &lt;code&gt;document.querySelector()&lt;/code&gt; you will get a HTML element or, if it does not match anything in the DOM, null. It&#39;s very easy to overlook this null and not handle it appropriately. TypeScript has you covered.&lt;/p&gt;
&lt;p&gt;It&#39;s very useful when working with objects or arrays, making sure that all types, structures and properties are present and correct. Imagine you&#39;re building up an object to post to an API. If one of the properties you send is undefined, maybe because it has not yet been set, then it may fail. TypeScript will alert you to the possibility of this being undefined so you can prevent the problem.&lt;/p&gt;
&lt;p&gt;In short, it makes your JavaScript more secure and helps you pick up issues much earlier in the development cycle so they don&#39;t become bugs.&lt;/p&gt;
</description>
      <pubDate>Sat, 20 Jan 2024 11:05:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2024/learning-typescript/</guid>
    </item>
    <item>
      <title>Rebranding Tips - Part 4 - Typography</title>
      <link>https://chrissmith.xyz/blog/2024/rebranding-tips-part-4-typography/</link>
      <description>&lt;p&gt;I&#39;ve been through a number of website or apps rebranding exercises, ranging from just a logo update to full blown name, domain and colour scheme and typographical changes. I thought I&#39;d share some of the oddities that cropped up for me and some tips.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Typography&lt;/h2&gt;
&lt;p&gt;Typography is not just the font-family but also font weight, font size, the relative sizes and weights of different text elements and even what fallbacks are used.&lt;/p&gt;
&lt;h2&gt;Consistency first&lt;/h2&gt;
&lt;p&gt;Generally speaking most sites or apps don&#39;t use too many fonts, usually just one for headings or notable elements and one for the body text. With a site or app that isn&#39;t strictly organised it&#39;s well worth trying to align everything in the existing typography before starting. Make sure that headings are the right font, size and weight so that everything is consistent.&lt;/p&gt;
&lt;p&gt;Theoretically, if everything is well organised then swapping out font families should be easy.&lt;/p&gt;
&lt;h2&gt;Sizes and weights&lt;/h2&gt;
&lt;p&gt;If one set of guidelines uses more or fewer styles than another it can harder to align everything. The focus should always be on the best result using the new system rather than simply finding the closest match. Look at how the new system wants sizes and weights to be used and try to work towards this. It can be phased, matching first and refining later if there&#39;s a tight timeline. Minor differences in size and weight usually go unnoticed.&lt;/p&gt;
&lt;h2&gt;Accessibility&lt;/h2&gt;
&lt;p&gt;It&#39;s important to make sure that your headings are used in a logical hierarchy as this can be used for screen reader navigation.&lt;/p&gt;
&lt;p&gt;If a font has a particular character, for example, an art deco 1930s feel or a spiky horror film feel, then this should also be described to non screen users via aria attributes.&lt;/p&gt;
&lt;p&gt;If a font is very ornate and not necessarily easy for everyone to read, for example in a title, it may be worth repeating its content in a title attribute so that it can be read on hover. This is almost treating it as if it were an image.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;In this Rebranding Tips series:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://chrissmith.xyz/blog/rebranding-tips-part-1-logos&quot;&gt;Rebranding Tips - Part 1 - Logos&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://chrissmith.xyz/blog/rebranding-tips-part-2-brand-names&quot;&gt;Rebranding Tips - Part 2 - Brand Names&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://chrissmith.xyz/blog/rebranding-tips-part-3-colours&quot;&gt;Rebranding Tips - Part 3 - Colours&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Rebranding Tips - Part 4 - Typography&lt;/li&gt;
&lt;/ul&gt;
</description>
      <pubDate>Mon, 08 Jan 2024 16:33:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2024/rebranding-tips-part-4-typography/</guid>
    </item>
    <item>
      <title>Rebranding Tips - Part 3 - Colours</title>
      <link>https://chrissmith.xyz/blog/2024/rebranding-tips-part-3-colours/</link>
      <description>&lt;p&gt;I&#39;ve been through a number of website or apps rebranding exercises, ranging from just a logo update to full blown name, domain and colour scheme and typographical changes. I thought I&#39;d share some of the oddities that cropped up for me and some tips.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Colours&lt;/h2&gt;
&lt;p&gt;I&#39;ll start with an oddity. In a big codebase that had evolved over a long time with lots of different parts, I once counted 15 different versions of what was supposedly the same green. Some were a HTML colour name, some hex, some RGB.&lt;/p&gt;
&lt;h2&gt;Consistency first&lt;/h2&gt;
&lt;p&gt;This widespread variation of colours taught me something valuable. You can&#39;t just get into a replace operation. You need to get your old colours lined up first. If you can reach a point where each colour is defined once, with a single source of truth then it makes changing it much easier.&lt;/p&gt;
&lt;p&gt;It&#39;s important to document your colour scheme somewhere where all designers and developers can get it easily so they use the right values. This is fairly standard practice these days but wasn&#39;t in the past and still might not be for smaller projects.&lt;/p&gt;
&lt;p&gt;Once you have your well defined colours it&#39;s now relatively easy to switch out the old for the new but there can still be some hiccups.&lt;/p&gt;
&lt;h2&gt;Colour frameworks&lt;/h2&gt;
&lt;p&gt;Some colour schemes will have a primary colour and then neutrals - black white and various shades of grey. Others will have a primary and a secondary as well as neutrals. Moving from one colour list to another can be hard if they don&#39;t naturally align.&lt;/p&gt;
&lt;h2&gt;Neutrals&lt;/h2&gt;
&lt;p&gt;It&#39;s probably easiest to tackle the neutrals first. How many shades does each scheme contain? Your focus should not be on finding the nearest match for each but on how the new branding would want the various shades to be used. Is a light grey only intended to be used as an alternative background colour to white? Maybe it&#39;s not suitable for text as it doesn&#39;t have sufficient contrast against white. It&#39;s important to know what combinations of shades can be used together to provide enough contrast to be accessible.&lt;/p&gt;
&lt;p&gt;If you&#39;re moving from a scheme which has 3 greys to one which has 10, rather than match 3 look at the branding guidelines or existing uses to see whcih is best for each use case. This is a lengthy process to do right but you do have the option of a phased approach, matching the closest shade initially and then taking a more refined approach later. In my experience people don&#39;t generally get offended by a shade of grey being suboptimal like they might with primary brand colours.&lt;/p&gt;
&lt;h2&gt;Status colours&lt;/h2&gt;
&lt;p&gt;Colours that are used exclusively to communicate statuses, such as success, errors, warnings, or information are usually quite straightforward to adapt. A well designed colour scheme should have these clearly defined.&lt;/p&gt;
&lt;p&gt;I&#39;ve come across a situation where the old colour scheme had additional statuses that the new scheme did not consider. For example, we had &amp;quot;expired&amp;quot; (red/error), &amp;quot;expiring&amp;quot; (amber/warning), &amp;quot;valid&amp;quot; (green/success), &amp;quot;new&amp;quot; (blue/info) but also &amp;quot;pending&amp;quot;. In this case I chose to use a neutral grey so as not to introduce anything new from outside the overall colour scheme.&lt;/p&gt;
&lt;h2&gt;Brand colours&lt;/h2&gt;
&lt;p&gt;The use of the primary brand colour is usually the most contentious issue. Hopefully it&#39;s a like for like swap but it can be harder. I&#39;ve encounterted the situation where the old scheme had a single primary brand colour but the new scheme has 2 main colours. You need to work out what to use where and think about the balance.&lt;/p&gt;
&lt;p&gt;Imagine a website for a coffee shop with an Italian theme, where the design is to use lots of green and red on white, like the Italian flag. I don&#39;t know if anything this corny really exists anywhere but it illustrates the point. It would need to use both colours for the idea to work so it can&#39;t just swap the old colour, say brown, to just red. This becomes quite a manual, design driven process so takes longer than a simple code change.&lt;/p&gt;
&lt;p&gt;Of course, you may get the opposite where more colours become fewer, but that&#39;s much easier.&lt;/p&gt;
&lt;h2&gt;Semantics&lt;/h2&gt;
&lt;p&gt;To throw in a general bit of design theory, it&#39;s important for any interactive elements such as buttons or links to be obvious. Ideally you&#39;d use unique colours for links, not the same colour as headings, so that it&#39;s immediately obvious to a user what can be clicked and what can&#39;t.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;In this Rebranding Tips series:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://chrissmith.xyz/blog/rebranding-tips-part-1-logos&quot;&gt;Rebranding Tips - Part 1 - Logos&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://chrissmith.xyz/blog/rebranding-tips-part-2-brand-names&quot;&gt;Rebranding Tips - Part 2 - Brand Names&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Rebranding Tips - Part 3 - Colours&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://chrissmith.xyz/blog/rebranding-tips-part-4-typography&quot;&gt;Rebranding Tips - Part 4 - Typography&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
      <pubDate>Mon, 08 Jan 2024 16:32:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2024/rebranding-tips-part-3-colours/</guid>
    </item>
    <item>
      <title>Rebranding Tips - Part 2 - Brand Names</title>
      <link>https://chrissmith.xyz/blog/2024/rebranding-tips-part-2-brand-names/</link>
      <description>&lt;p&gt;I&#39;ve been through a number of website or apps rebranding exercises, ranging from just a logo update to full blown name, domain and colour scheme and typographical changes. I thought I&#39;d share some of the oddities that cropped up for me and some tips.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Brand names&lt;/h2&gt;
&lt;p&gt;You might think that updating brand names is as simple as a text find and replace but there can be more to it. Text can be hidden away in templates, config files and databases.&lt;/p&gt;
&lt;h2&gt;Casing&lt;/h2&gt;
&lt;p&gt;How a brand name appears in text can be important. Some names are always used in lowercase, some always uppercase, some title case and some sentence case. You have to be careful that this casing is how the text naturally appears is not set by CSS or JavaScript or somehow manipulated in the backend. It&#39;s probably a good idea to remove anything that sets this and make the natural text appear as expected.&lt;/p&gt;
&lt;h2&gt;Context&lt;/h2&gt;
&lt;p&gt;Another oddity I&#39;ve come across is that some names can contain a certain word or meaning that no longer fits the context. For example, if the old company name was &amp;quot;Oldco&amp;quot; and we had something that said &amp;quot;OldCo services&amp;quot; but the new company name is &amp;quot;NewCo Services&amp;quot; then &amp;quot;NewCo Services services&amp;quot; feels weird. You may need to manually check for how the name is used if it contains real words and rewrite some text.&lt;/p&gt;
&lt;h2&gt;Email addresses&lt;/h2&gt;
&lt;p&gt;If a domain is changing or we at least want to stop using the old name in any display text then there&#39;s a way of doing this. Suppose our page says &amp;quot;For help please email support@oldco.com&amp;quot;. It&#39;s mentioning OldCo, which we want to avoid. Instead of just substituting the new name email address (if there is one) it&#39;s better to change the link so that we get something like &amp;quot;For help please &amp;lt;email our support team&amp;gt;&amp;quot; with the text in angled brackets linked to the email address. This not only conceals the old domain name but now uses meaningful hyperlink text, which is better for user experience and accessibility.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;In this Rebranding Tips series:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://chrissmith.xyz/blog/rebranding-tips-part-1-logos&quot;&gt;Rebranding Tips - Part 1 - Logos&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Rebranding Tips - Part 2 - Brand Names&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://chrissmith.xyz/blog/rebranding-tips-part-3-colours&quot;&gt;Rebranding Tips - Part 3 - Colours&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://chrissmith.xyz/blog/rebranding-tips-part-4-typography&quot;&gt;Rebranding Tips - Part 4 - Typography&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
      <pubDate>Mon, 08 Jan 2024 16:31:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2024/rebranding-tips-part-2-brand-names/</guid>
    </item>
    <item>
      <title>Rebranding Tips - Part 1 - Logos</title>
      <link>https://chrissmith.xyz/blog/2024/rebranding-tips-part-1-logos/</link>
      <description>&lt;p&gt;I&#39;ve been through a number of website or apps rebranding exercises, ranging from just a logo update to full blown name, domain and colour scheme and typographical changes. I thought I&#39;d share some of the oddities that cropped up for me and some tips.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Logos&lt;/h2&gt;
&lt;p&gt;At the face of it, switching out an old logo for a new one seems pretty straightforward and it kind of is, but rather than just switch can we take the opportunity to improve the implementation?&lt;/p&gt;
&lt;h2&gt;Performance and optimisation&lt;/h2&gt;
&lt;p&gt;When we add the new logo, we probably have the opportunity to use a newer image format, SVG, WebP or AVIF. SVG&#39;s vector format will improve sharpness and the others will reduce file size. For the non vector formats I&#39;d suggest serving an image that is 2 to 2.5 times the size displayed on screen so the pixel density is high and it looks crisp on high quality displays. So, if it shows at 200px wide by 100px high, use a 500x250 original.&lt;/p&gt;
&lt;h2&gt;Accessibility&lt;/h2&gt;
&lt;p&gt;It&#39;s also worth ensuring that it&#39;s accessible. If it&#39;s an image tag put text in the alt attribute to describe it. If it&#39;s an SVG tag, add an accessible title.&lt;/p&gt;
&lt;p&gt;Consider dark mode. Does the image contain dark colours that would not show up on a darker background. It may be worth serving an alternative version, maybe an all white version.&lt;/p&gt;
&lt;h2&gt;Branding&lt;/h2&gt;
&lt;p&gt;One oddity that I&#39;ve come across is moving to a set of branding guidelines that were very strict about the usage of a logo, that it must not be used below a certain size, that it must have a certain margin around it, etc. This can be tricky if it does not fit the page layout. You may be forced to redesign it slightly. Just something worth bearing in mind when planning the work.&lt;/p&gt;
&lt;h2&gt;Come out, logos, wherever you are&lt;/h2&gt;
&lt;p&gt;You might assume that it&#39;s easy to find the logos - just a quick code search, and if the site is not too complex or too old it might be that simple. For me, working with an old complex codebase that has been worked on by a lot of people over a lot of years it was much harder.&lt;/p&gt;
&lt;p&gt;Doing the search was a good starting point and found most of the pages or templates where logos were used but there were others hiding. Some were hiding away in base64 strings.&lt;/p&gt;
&lt;p&gt;Some were in CSS, being used a background images, which was probably a bad idea anyway so better not to just replace that. A logo should be considered content and appear in the HTML for accessibility reasons.&lt;/p&gt;
&lt;p&gt;Some were defined in XML or JSON files and then used as image src.&lt;/p&gt;
&lt;p&gt;And finally, some were coming from a database so did not appear in the code but were bound as image sources at run time.&lt;/p&gt;
&lt;p&gt;If you have any files in other formats such as PDFs it&#39;s worth checking these as they may contain hard coded images. I&#39;d suggest trying to move away from serving files to publishing HTML wherever possible. It&#39;s better for accessibility and search engine discoverability, not to mention easier to maintain.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;In this Rebranding Tips series:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Rebranding Tips - Part 1 - Logos&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://chrissmith.xyz/blog/rebranding-tips-part-2-brand-names&quot;&gt;Rebranding Tips - Part 2 - Brand Names&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://chrissmith.xyz/blog/rebranding-tips-part-3-colours&quot;&gt;Rebranding Tips - Part 3 - Colours&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://chrissmith.xyz/blog/rebranding-tips-part-4-typography&quot;&gt;Rebranding Tips - Part 4 - Typography&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
      <pubDate>Mon, 08 Jan 2024 16:30:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2024/rebranding-tips-part-1-logos/</guid>
    </item>
    <item>
      <title>What to Validate on a Form</title>
      <link>https://chrissmith.xyz/blog/2023/what-to-validate-on-a-form/</link>
      <description>&lt;p&gt;We all know that validating user input is a good idea but how do you decide on what rules to apply?&lt;/p&gt;
&lt;h2&gt;What are the aims of validation?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Protecting us against any malicious input.&lt;/li&gt;
&lt;li&gt;Protecting the system&#39;s data integrity.&lt;/li&gt;
&lt;li&gt;Protecting the user against data entry mistakes.&lt;/li&gt;
&lt;li&gt;Protecting our UI against things we&#39;re not able to output.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;What can we do?&lt;/h2&gt;
&lt;p&gt;We can limit the data type by applying the appropriate input type attribute - number, date, email, url, etc. That will constrain the data to only the type expected. It may also help with input by bringing up the appropriate on screen keyboard.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;input type=&amp;quot;email&amp;quot;&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;We can constrain length or range with attributes like min, max, maxlength, minlength.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;input type=&amp;quot;number&amp;quot; min=&amp;quot;0&amp;quot; max=&amp;quot;100&amp;quot;&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;We can do pattern matching, using regex to only accept certain string formats.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;input type=&amp;quot;text&amp;quot; pattern=&amp;quot;^[a-zA-Z0-9]$&amp;quot;&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;What should we do?&lt;/h2&gt;
&lt;p&gt;This is the harder question.&lt;/p&gt;
&lt;h3&gt;Security&lt;/h3&gt;
&lt;p&gt;Firstly, let&#39;s think about security and protecting against malicious intentions. We can use pattern matching to restrict the characters entered to only those that are needed. For example, a phone number field can be restricted to numbers and, if you&#39;re feeling generous, spaces, brackets and dashes. We should work out what characters are needed and use regex to only allow those.&lt;/p&gt;
&lt;p&gt;The main thing to remember from a security point of view is to do this validation on the server as the front end can be bypassed. It&#39;s here for convenience, not security. It&#39;s the smiley person opening the door for guests, not the mean looking security guard.&lt;/p&gt;
&lt;h3&gt;Constraints&lt;/h3&gt;
&lt;p&gt;Thinking about the other considerations, let&#39;s set sensible minimum and maximum sizes on things.&lt;/p&gt;
&lt;p&gt;How long or short can a phone number really be? If they&#39;re putting in something that&#39;s 30 digits long then chances are they&#39;ve accidentally pasted it twice, or are copying the wrong number from something else.&lt;/p&gt;
&lt;p&gt;What&#39;s a reasonable length for a first name? Surely there comes a point, when it gets really long, when they have a shorter form they can use?&lt;/p&gt;
&lt;p&gt;How far into the future can a date be set? Is there ever any point in setting something more than 30 years ahead? What are the chances of this system being around then and this data still being relevant?&lt;/p&gt;
&lt;p&gt;There&#39;s a skill to making sure things aren&#39;t too open but not so closed as to cause a problem with genuine data.&lt;/p&gt;
&lt;h3&gt;Ask for the right things&lt;/h3&gt;
&lt;p&gt;Also, think about the tone and how the data will be used. If you put &amp;quot;First name&amp;quot; as your label you might get a different, more formal value than if you use &amp;quot;What shall we call you?&amp;quot;.&lt;/p&gt;
&lt;p&gt;Another option is to use warning prompts rather than an absolute pass or fail. If a name is long, you can prompt &amp;quot;That&#39;s a long name. Is there a shorter version you prefer to use?&amp;quot;. Or you could reveal a second input for a nickname or short name. That way you can accept the long form if they prefer but you&#39;re reducing the risk of handling something you might have to output ungracefully with ellipsis later.&lt;/p&gt;
&lt;p&gt;We can use JavaScript to listen for the invalid event and reveal an alternative input.&lt;/p&gt;
&lt;h3&gt;Tell them what you expect&lt;/h3&gt;
&lt;p&gt;Asking someone to input some data without any instructions and then telling them off for doing it wrong is just rude. Give them hints with placeholders or some help text. As well as not annoying users it makes data entry much quicker.&lt;/p&gt;
</description>
      <pubDate>Fri, 27 Oct 2023 14:30:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2023/what-to-validate-on-a-form/</guid>
    </item>
    <item>
      <title>Pronunciation of Terms in Web Development</title>
      <link>https://chrissmith.xyz/blog/2023/pronunciation-of-terms-in-web-development/</link>
      <description>&lt;p&gt;Yesterday I was on a call and mentioned that I&#39;d done some pattern matching using regex and as I said it I suddenly felt very self-conscious about how I&#39;d pronounced it.&lt;/p&gt;
&lt;h2&gt;Regex&lt;/h2&gt;
&lt;p&gt;Is it &amp;quot;reggex&amp;quot; with a hard G like &amp;quot;egg&amp;quot;, or &amp;quot;redgex&amp;quot; with a soft G like in &amp;quot;agenda&amp;quot;? I think we have probably all heard both at some point and so it&#39;s an unresolved question with no definitive right or wrong. What&#39;s interesting to me is where people land and why.&lt;/p&gt;
&lt;p&gt;The word regex is a contracted form of &amp;quot;regular expression&amp;quot; so the original G is hard. Some people see this logic and want to preserve the original G sound. This preference is based in logic and showing you understand the origin.&lt;/p&gt;
&lt;p&gt;Others worry less about the original sound and view it as a new independent word, approaching it as they would expect it to be pronounced. The EGE pattern is usually pronounced with a soft G sound, e.g. regenerate, egestion.&lt;/p&gt;
&lt;p&gt;Some people may approach this from a natural language point of view but, if English is not their first language and they are more used to a hard G in this pattern, then they may swing this way.&lt;/p&gt;
&lt;h2&gt;GIF&lt;/h2&gt;
&lt;p&gt;The conversation that everybody hates. Is it pronounced like &amp;quot;gift&amp;quot; or &amp;quot;jiffy&amp;quot;? The origin is Graphical Interface Format with a hard G but English has words &amp;quot;git&amp;quot;, &amp;quot;gibbon&amp;quot; (hard G) and &amp;quot;ginger&amp;quot;, &amp;quot;gist&amp;quot; (soft G) as well as names &amp;quot;Gideon&amp;quot;, &amp;quot;Gillian&amp;quot;, so it&#39;s anyone&#39;s guess.&lt;/p&gt;
&lt;p&gt;Git doesn&#39;t seem to have this debate and we&#39;re not starting it here. Maybe they learnt from GIF and went out of their way to make it definitive early?&lt;/p&gt;
&lt;h2&gt;Whatever&lt;/h2&gt;
&lt;p&gt;My inconclusive conclusion is that either is fine and we just shouldn&#39;t worry about it, no more than we worry about US vs UK English. They&#39;re different because we&#39;re from different backgrounds or wired differently, and that keeps things interesting.&lt;/p&gt;
</description>
      <pubDate>Wed, 18 Oct 2023 17:10:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2023/pronunciation-of-terms-in-web-development/</guid>
    </item>
    <item>
      <title>How Widespread is Ad Blocking?</title>
      <link>https://chrissmith.xyz/blog/2023/how-widespread-is-ad-blocking/</link>
      <description>&lt;p&gt;Have you ever tried to read a blog post or article and found it really hard work because of all the ads? Banner ads appearing between paragraphs, videos hugging the bottom of the screen, the odd modal appearing. It&#39;s too much.&lt;/p&gt;
&lt;p&gt;After not using them for over a decade, I&#39;ve now gone back to installing an ad blocker browser extension. And it mostly makes my experience of browsing the internet better. I can focus on the content I want without all the noise.&lt;/p&gt;
&lt;p&gt;Now, whether or not we should use ad blockers, and deny sites this revenue stream, possibly their only revenue stream, is a whole debate in itself. I won&#39;t get into all that here. I&#39;m more interested in some other side effects I&#39;ve discovered from starting to use one again.&lt;/p&gt;
&lt;h2&gt;Different Services&lt;/h2&gt;
&lt;p&gt;As well as ad blocking browser extensions there are also VPN services that offer to block ads, internet or broadband providers who offer this as an extra, mobile network providers. When you start adding all of those up it could be quite a proportion of users.&lt;/p&gt;
&lt;h2&gt;Tracking and Analytics&lt;/h2&gt;
&lt;p&gt;From using my browser&#39;s console and network tabs I noticed that some content on my own sites is now being blocked. Tracking software, like Google Analytics, gets blocked. So, in theory, when I visit a page now, the owner will not know. This got me thinking. How many people are using ad blockers and how does this affect the numbers we see in tools like Google Analytics?&lt;/p&gt;
&lt;h2&gt;Numbers&lt;/h2&gt;
&lt;p&gt;After some research, reading a few posts from the last couple of years, I got some percentages. The numbers being from different sources varied but they all seemed to agree on certain factors. The likelihood of using ad blocking varies by geography, age and device type. Younger people block more, mobile devices block more and the UK and US don&#39;t block as much as other nations. Maybe that&#39;s a capitalist, pro advertising thing? Who knows? Of all the big numbers quoted, the percentage estimated to be blocked ranged from about 30 to 40 percent. Not that much variation. It seems that most sources agree it&#39;s broadly in that range.&lt;/p&gt;
&lt;p&gt;So, if we take a conservative estimate from this and work on the assumption it&#39;s roughly a third of users, what does that mean for our analytics data? Well it means that we might only be seeing two thirds of our actual traffic. So, maybe we should be estimating actual traffic at 1.5 times what is recorded.&lt;/p&gt;
&lt;p&gt;If our site serves ads, maybe the numbers recorded in analytics tracking are an accurate reflection of how many visitors will see our ads.&lt;/p&gt;
&lt;h2&gt;Handling Blockers&lt;/h2&gt;
&lt;p&gt;If we know that a high proportion of visitors are blocking our ads, how does our page handle this content being blocked? Do we test this scenario, viewing the page with an ad blocker on? Can we serve alternate content (probably not more ads) if this fails to load? Maybe a message asking users for their support and requesting that they disable the ad blocker for this site?&lt;/p&gt;
&lt;p&gt;Or we could even play hard ball and make loading content conditional on ads loading. I probably wouldn&#39;t recommend this route as you&#39;re putting your whole site at the mercy of another service&#39;s availability.&lt;/p&gt;
</description>
      <pubDate>Mon, 09 Oct 2023 17:10:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2023/how-widespread-is-ad-blocking/</guid>
    </item>
    <item>
      <title>Practical Tips to Reduce your Carbon Footprint</title>
      <link>https://chrissmith.xyz/blog/2023/practical-tips-to-reduce-your-carbon-footprint/</link>
      <description>&lt;p&gt;If you&#39;re a developer, like me, or someone who works on a computer all day, here are some ways you can reduce your carbon footprint. Essentially it&#39;s all about saving energy and reducing any wasted energy from our daily routine. If you work from home it can help reduce your energy bills too.&lt;/p&gt;
&lt;h2&gt;Computer power&lt;/h2&gt;
&lt;p&gt;Computers still use a lot of energy when in standby or sleep modes. If you&#39;re not going to use your computer for a couple of hours, shut it down fully, switching off at the plug.&lt;/p&gt;
&lt;p&gt;Set your computer to go into standby or sleep mode when left idle for a few minutes. It&#39;ll still use power but at a lower rate.&lt;/p&gt;
&lt;p&gt;Reduce your monitor brightness if you don&#39;t need it. Reducing this from 100% to 70% can save 20% of the energy your monitor uses.&lt;/p&gt;
&lt;p&gt;If you just need to do a quick search for something that does not require the use of a desktop screen, use your phone instead. It still uses power obviously but not as much.&lt;/p&gt;
&lt;h2&gt;Reduce work&lt;/h2&gt;
&lt;p&gt;Bookmark sites you visit regularly and visit them directly. Going via a search engine each time uses more energy.&lt;/p&gt;
&lt;p&gt;Avoid any unneccessary video streaming. Can you use an audio version, like a podcast, instead? Is there a text transcript available? Turn off any auto-play features so that you don&#39;t start streaming unwanted video content. Close tabs that you&#39;re not using to stop them from streaming video or audio in the background.&lt;/p&gt;
&lt;p&gt;Reduce the number of emails you send and receive. Talk in person if you can. Try not to reply to all. Unsubscribe from any newsletters that you don&#39;t actually read. Don&#39;t send email newletters to people who may no longer want them - check periodically.&lt;/p&gt;
&lt;p&gt;Does the whole team need to be in a video call? Could just 2 or 3 people handle it just as well?&lt;/p&gt;
&lt;h2&gt;Logistics&lt;/h2&gt;
&lt;p&gt;Work with and support companies who are committed to reducing their carbon footprint, ideally those who run on renewable energy sources.&lt;/p&gt;
&lt;p&gt;Avoid changing your hardware too often if you can. Shipping hardware across the globe has a big impact.&lt;/p&gt;
</description>
      <pubDate>Wed, 13 Sep 2023 17:40:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2023/practical-tips-to-reduce-your-carbon-footprint/</guid>
    </item>
    <item>
      <title>WordPress to Eleventy - Part 2, The How</title>
      <link>https://chrissmith.xyz/blog/2023/wordpress-to-eleventy-part-2-the-how/</link>
      <description>&lt;p&gt;Having made the decision to migrate my site from &lt;a href=&quot;https://en-gb.wordpress.org/&quot;&gt;WordPress&lt;/a&gt; to &lt;a href=&quot;https://www.11ty.dev/&quot;&gt;Eleventy&lt;/a&gt;, actually getting into it was quite daunting. In fact, I put off doing it for a few months. I&#39;m not going to lie, it was a bit of work, but not too bad. I mean, I&#39;d do it again.&lt;/p&gt;
&lt;h2&gt;Exporting from WordPress&lt;/h2&gt;
&lt;p&gt;This was probably the easiest part. WordPress makes it nice and easy to get your data out. You can do it through a number of plugins or from the database direct. My hosting plan had a control panel with the MySql database with easy export options. I had a choice of exporting to JSON, XML, CSV, all sorts. Not really knowing what I was doing yet, I grabbed an export in every format, just in case. You only need JSON. It gives you a bit array of post objects.&lt;/p&gt;
&lt;h2&gt;New Eleventy site&lt;/h2&gt;
&lt;h3&gt;Eleventy and GitHub&lt;/h3&gt;
&lt;p&gt;I created a new GitHub repo and following the excellent Eleventy docs installed a new instance of Eleventy with npm. Running it via the command line gets you to a static page quite quickly and easily. You can then start playing with the underlying HTML, add CSS and, by reading more of the docs, start adding some more functionality like loops or repeated templates. It&#39;s really not hard to use and so flexible with interchangable syntax across templating languages.&lt;/p&gt;
&lt;h3&gt;Netlify&lt;/h3&gt;
&lt;p&gt;For hosting I used Netlify. I&#39;ve used it before for a static site and it&#39;s superb. It&#39;s free, which is always a winner. Following documentation across Eleventy and Netlify it was quite simple to set up a new site, point it at the GitHub repo (giving it permissions) and have it all set to deploy whenever the repo changes. So, now I make changes on my local machine, push them in GitHub desktop and they&#39;re live within about 30 seconds.&lt;/p&gt;
&lt;h2&gt;Importing into Eleventy&lt;/h2&gt;
&lt;p&gt;With the site all set up and a basic template in place, I now needed to restore my old posts. I had two options here - either manually copy the text from the JSON into new HTML files or find a way of looping through the JSON and transforming each post into a new file. I decided to do both. Thinking that the transform might be hard and take time I thought that if I could manually copy the last few posts then it would allow me to get the site up as quickly as possible. I could then backfill the others at my leisure. Pressure off. So, I manually copied 5 posts, built it all, pushed to GitHub and it went live.&lt;/p&gt;
&lt;h3&gt;Data cleansing&lt;/h3&gt;
&lt;p&gt;Working with the WordPress data export had some challenges, maybe some that I would not have faced if I&#39;d used an export plugin with more options. One challenge was that it not only had an object for each post but also each post revision, so every time I made a change to a post it would have both full versions in the data. Making a new working copy of the JSON, I had to manually trawl through the posts and where there was duplicated content, remove all but the most recent version.&lt;/p&gt;
&lt;p&gt;Another issue was the content type. It created a record for each image attachment and also for any static pages that weren&#39;t posts. More manual tidying up.&lt;/p&gt;
&lt;p&gt;Finally, it also contained posts that weren&#39;t actually ever published, all the drafts. I removed these too leaving a slimmed down JSON file with just my actual posts. I suspect that filtering out these records might have been an option in a better export tool.&lt;/p&gt;
&lt;h2&gt;Creating the posts&lt;/h2&gt;
&lt;p&gt;This would have been hard, for me at least, if it wasn&#39;t for this amazing post by Heydon Pickering.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://heydonworks.com/article/wordpress-to-eleventy/&quot;&gt;From WordPress to Eleventy with Ease&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Heydon created a node script that uses the json-to-frontmatter-markdown package to transform the WordPress post data JSON into frontmatter plus markdown.&lt;/p&gt;
&lt;p&gt;I tried running it and got errors but the error messages were helpful and I was gradually able to fix minor data errors, usually things missing or unusual syntax in the JSON. After a few goes it worked and filled my target folder with new files. Yay! But, it wasn&#39;t quite right. No problem. It&#39;s easy to just empty out the folder, make tweaks to the script and run it again. After a few more goes I got what I wanted and had lots of markdown files with just the right frontmatter and content.&lt;/p&gt;
&lt;h2&gt;Tidying up&lt;/h2&gt;
&lt;p&gt;On publishing the posts locally, there were still issues - odd bits of formatting not handled quite right by markdown, broken links, missing images, the wrong kind of quote marks. But now these could be fixed in the markdown files rather than the JSON. And once you&#39;ve found an issue you can search for other occurrences and fix those too.&lt;/p&gt;
&lt;p&gt;As you can see, the majority of the work is not really technical, it&#39;s more about having the data in good shape and looking out for things that are not quite as expected.&lt;/p&gt;
&lt;h2&gt;New content&lt;/h2&gt;
&lt;p&gt;So, now I write new posts in markdown, in VS Code (that&#39;s what I&#39;m doing right now), edit the frontmatter, push changes and the post is live.&lt;/p&gt;
&lt;h2&gt;Why?&lt;/h2&gt;
&lt;p&gt;So, why did I decide to move from one to the other? I&#39;ve covered that in a separate post.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://chrissmith.xyz/blog/2023/wordpress-to-eleventy-part-1-the-why&quot;&gt;WordPress to Eleventy - Part 1, The Why&lt;/a&gt;&lt;/p&gt;
</description>
      <pubDate>Sun, 18 Jun 2023 14:00:01 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2023/wordpress-to-eleventy-part-2-the-how/</guid>
    </item>
    <item>
      <title>WordPress to Eleventy - Part 1, The Why</title>
      <link>https://chrissmith.xyz/blog/2023/wordpress-to-eleventy-part-1-the-why/</link>
      <description>&lt;p&gt;For years my personal website used &lt;a href=&quot;https://en-gb.wordpress.org/&quot;&gt;WordPress&lt;/a&gt;. It&#39;s now using &lt;a href=&quot;https://www.11ty.dev/&quot;&gt;Eleventy&lt;/a&gt;. I thought it might be interesting to others to look at why I&#39;ve made the change.&lt;/p&gt;
&lt;h2&gt;WordPress&lt;/h2&gt;
&lt;p&gt;I started using WordPress in 2008 and never really looked back, until 2022. So, that&#39;s a solid 15 years of WordPress, and, honestly I don&#39;t have a bad word to say about it, it&#39;s great.&lt;/p&gt;
&lt;h3&gt;The pros&lt;/h3&gt;
&lt;p&gt;WordPress makes blogging or content management very easy. It&#39;s hosted online so as long as you can login you can edit it from anywhere. It also has great apps so you can have an idea for a blog post while out and about and start drafting something and then later sync it up and carry on. That&#39;s quite powerful.&lt;/p&gt;
&lt;p&gt;There&#39;s a huge community, loads of free plugins for adding additional functionality usually with zero code, just a bit of config, loads of free configurable themes so you can find the right look.&lt;/p&gt;
&lt;h3&gt;The cons&lt;/h3&gt;
&lt;p&gt;The platform is constantly evolving, as are the plugins and themes. On the one hand this is a good thing; on the other it adds a maintenance overhead. There&#39;s always something that needs to be updated, and occasionally causes a big problem. I had issues when my (admittedly cheap) hosting didn&#39;t offer a high enough version of PHP to support some features.&lt;/p&gt;
&lt;p&gt;As WordPress uses a MySql database, a lot of the set up involved doing back end work, which is not what I want to be spending my time on. The use of a database also means having to pay for database hosting, which can get expensive. Not a lot of money but a blog starts becoming an expensive hobby if no money is coming in from it.&lt;/p&gt;
&lt;h2&gt;Eleventy&lt;/h2&gt;
&lt;p&gt;My website is now built with Eleventy. It&#39;s quite a different set up.&lt;/p&gt;
&lt;h3&gt;The pros&lt;/h3&gt;
&lt;p&gt;It&#39;s all static HTML files, which means it&#39;s really fast, like stupidly fast. I now feel I have full control as every bit of content is created by me from scratch, no plugins with black box magic in them. There&#39;s no imported theme - every bit of HTML and CSS is my own so I don&#39;t ever have to wrestle against any constraints of an existing system or template.&lt;/p&gt;
&lt;p&gt;I don&#39;t have the fancy editor of WordPress but I now write markdown files, which is easy, and I even have markdown editor apps on my phone shoudl I get the urge to start something when away from my desk.&lt;/p&gt;
&lt;p&gt;As it&#39;s all static pages, I can host it for free.&lt;/p&gt;
&lt;h3&gt;The cons&lt;/h3&gt;
&lt;p&gt;To be honest, I don&#39;t really see any. I don&#39;t feel there&#39;s anything I had before that I&#39;m missing or that I can&#39;t achieve.&lt;/p&gt;
&lt;h2&gt;How?&lt;/h2&gt;
&lt;p&gt;So, how did I go about moving from one to the other? I&#39;ve covered that in a separate post.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://chrissmith.xyz/blog/2023/wordpress-to-eleventy-part-2-the-how&quot;&gt;WordPress to Eleventy - Part 2, The How&lt;/a&gt;&lt;/p&gt;
</description>
      <pubDate>Sun, 18 Jun 2023 14:00:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2023/wordpress-to-eleventy-part-1-the-why/</guid>
    </item>
    <item>
      <title>Who&#39;d be a front end developer?</title>
      <link>https://chrissmith.xyz/blog/2023/whod-be-a-front-end-developer/</link>
      <description>&lt;p&gt;I&#39;m going to try to explain what a front end developer does, or, at least, should be doing, for those that don&#39;t know.&lt;/p&gt;
&lt;p&gt;Imagine you&#39;ve been tasked with designing a poster. You&#39;re given the text and a selection images and you arrange them in a pleasing way. Job done.&lt;/p&gt;
&lt;p&gt;That&#39;s all front end dev really is, right? Errr... no. Not by a long way.&lt;/p&gt;
&lt;h2&gt;Sizing&lt;/h2&gt;
&lt;p&gt;Now imagine that you&#39;re told your poster can magically change size. Spooky. In fact, it can be any size, so you need to make all the content flow and adapt so that it still always looks pleasing whether it&#39;s a square, a tall column or a long landscape view. I mean, your poster might even be glued onto the face of a watch (pushing the metaphor to breaking point). So, any size. How much longer does it take you now?&lt;/p&gt;
&lt;h2&gt;Timing&lt;/h2&gt;
&lt;p&gt;But it&#39;s not just size that varies. The different bits of content, text and images, are not all given to you up front. They may become available to use at different times and you don&#39;t always know what they will look like. But plan how you will display them at all sizes anyway. If things are available at different times but they flow, one after another, then how do you stop them jumping about as they&#39;re added? If something&#39;s taking a while to show up, how do you let people know it&#39;s on its way? Hmm, bit more to think about.&lt;/p&gt;
&lt;h2&gt;Describing&lt;/h2&gt;
&lt;p&gt;If this hadn&#39;t become challenging enough, now you&#39;ve got to think about making your poster content available to everyone. That&#39;s people who use other languages and even people who can&#39;t see it. It needs to be set up in a way which allows text to be available to translate and the layout flexible enough to also show right-to-left languages such as Arabic. That means not saying this text goes on the left but this text goes at the start of the line. For those that can&#39;t see it, you need to describe everything in words that can be read aloud - audio description.&lt;/p&gt;
&lt;h2&gt;Real world&lt;/h2&gt;
&lt;p&gt;Shattering the metaphor (finally) and bringing it back to the web these considerations are known as responsive design (sizing), loading strategy (content availability) and accessibility (available to everyone).&lt;/p&gt;
&lt;p&gt;And that&#39;s not even it. There&#39;s also performance (speed), user experience, branding, search engine optimisation for public sites, knowing which browser features you can and can&#39;t use.&lt;/p&gt;
&lt;p&gt;Easy, right?&lt;/p&gt;
</description>
      <pubDate>Thu, 15 Jun 2023 08:00:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2023/whod-be-a-front-end-developer/</guid>
    </item>
    <item>
      <title>Prototyping in CodePen</title>
      <link>https://chrissmith.xyz/blog/2023/prototyping-in-codepen/</link>
      <description>&lt;p&gt;&lt;a href=&quot;https://codepen.io/&quot;&gt;CodePen&lt;/a&gt; is not only great for making demos or experimenting but can also be used for prototyping.&lt;/p&gt;
&lt;p&gt;Personally, I&#39;ve never been a big fan of prototyping tools like Figma. I prefer to dive straight into code and play around with HTML and CSS. For me and my knowledge it&#39;s faster.&lt;/p&gt;
&lt;p&gt;Let&#39;s assume you have an existing app and want to add a new page. You want to be able to show something that looks like the finished page and is written in HTML, CSS and JavaScript. I&#39;ll explain how I&#39;d create a prototype like this in CodePen.&lt;/p&gt;
&lt;p&gt;It&#39;s worth a quick caveat that there is some initial setup to this so you&#39;ll only really reap the rewards if you&#39;re doing a few pens. You may also need a &lt;a href=&quot;https://codepen.io/features/pro&quot;&gt;CodePen Pro&lt;/a&gt; account to be able to use all the features mentioned.&lt;/p&gt;
&lt;h2&gt;Templating&lt;/h2&gt;
&lt;p&gt;The first phase is to recreate the app as a CodePen template. Create a new pen and give it a suitable template title. Now we need to add all our basic app shell content, HTML and CSS.&lt;/p&gt;
&lt;p&gt;Load up your app in a browser window, open DevTools on the Inspect or Elements tab and copy the DOM nodes inside the . Paste this into the HTML tab of your pen. The ensures that we get the final rendered content and don&#39;t need to worry about any server binding or scripts.&lt;/p&gt;
&lt;p&gt;You&#39;ll probably have references to external script files in your HTML. You can remove these or comment them out. We&#39;re not aiming to bring across all front end functionality but if you wanted to you could copy the script content into the pen&#39;s JS area, being careful to keep them in the right order.&lt;/p&gt;
&lt;p&gt;Now the CSS. Open the Network tab in DevTools and filter to CSS content. This shows all the CSS used. Anything in tags or inline will already be in your HTML so We&#39;re looking to copy in external CSS. We can either download the CSS files and upload them as assets (Pro feature) or copy the files&#39; content into the pen&#39;s CSS area, again in order.&lt;/p&gt;
&lt;p&gt;Hopefully you will now see a pen that looks like your app UI. Now identify any content in your HTML that is page specific rather than template and replace this with opening and closing comments so it&#39;s clear where to insert new content for prototypes.&lt;/p&gt;
&lt;p&gt;You&#39;ll need to do something similar with your CSS. Remove any specific styling that you won&#39;t need and add comments to make it clear what will be template styling and what will be new prototype specific content.&lt;/p&gt;
&lt;p&gt;Nearly there. Save this pen as a template, if you have this feature available. If not, you can fork it instead.&lt;/p&gt;
&lt;p&gt;Create a new pen from this template or fork it and add your new content. You now have a prototype in HTML, CSS and JavaScript.&lt;/p&gt;
&lt;h2&gt;Why this?&lt;/h2&gt;
&lt;p&gt;The advantage of this approach, as opposed to a UX tool, is that you can design and test for responsiveness, run Lighthouse audits in Debug mode, try different media settings like dark mode or reduced motion, all within the same prototype. It&#39;s also great for sharing with others and letting them play around.&lt;/p&gt;
</description>
      <pubDate>Fri, 09 Jun 2023 16:55:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2023/prototyping-in-codepen/</guid>
    </item>
    <item>
      <title>UI Performance - Critical Rendering Path Optimisation</title>
      <link>https://chrissmith.xyz/blog/2023/ui-performance-critical-rendering-path-optimisation/</link>
      <description>&lt;p&gt;A quick guide to how a web page renders and how we can ensure it stays fast. We tend to focus on load times and how quickly our requests receive responses. This focuses on what happens after that and how we keep the experience smooth for users.&lt;/p&gt;
&lt;h2&gt;How a page renders&lt;/h2&gt;
&lt;h3&gt;HTML and CSS&lt;/h3&gt;
&lt;p&gt;HTML is parsed to create the DOM (Document Object Model, a tree structure).&lt;/p&gt;
&lt;p&gt;CSS is parsed and all of the cascade, custom properties and calculations are done to arrive at final values. This creates the CSSOM (Cascading Stylesheet Object Model, another tree structure).&lt;/p&gt;
&lt;p&gt;The DOM and CSSOM are combined into the Render Tree. This decides what is rendered and how it is styled, e.g. an element with display: none will not be rendered.&lt;/p&gt;
&lt;p&gt;Next comes Layout. The browser has to calculate the exact size and position of every rendered element, and then which fit into the viewport.&lt;/p&gt;
&lt;p&gt;Now Paint. Now that the browser knows the exact size, position and styling of every element they&#39;re created as layers of rasterised images. As HTML and CSS are needed to reach this point these are always render blocking resources.&lt;/p&gt;
&lt;p&gt;Finally, there&#39;s a Composite step where these paint layers are brought together and this gives the rendered page.&lt;/p&gt;
&lt;p&gt;So, in terms of work for the browser, we&#39;ve got these 6 steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;HTML &amp;gt; DOM&lt;/li&gt;
&lt;li&gt;CSS calculations &amp;gt; CSSOM&lt;/li&gt;
&lt;li&gt;Render tree (DOM + CSSOM)&lt;/li&gt;
&lt;li&gt;Layout calculations&lt;/li&gt;
&lt;li&gt;Paint layers&lt;/li&gt;
&lt;li&gt;Composite&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This process of getting to the first render is called the Critical Rendering Path.&lt;/p&gt;
&lt;h3&gt;Fonts&lt;/h3&gt;
&lt;p&gt;Fonts are requested after the Render Tree, once the browser knows which font characters are needed. This can block rendering or, at least, the rendering of text until the font has loaded. By preloading the font in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; we can load it instantly from the cache when the time comes to use it.&lt;/p&gt;
&lt;h3&gt;JavaScript&lt;/h3&gt;
&lt;p&gt;When the browser hits a &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag it stops the rendering process until the script has finished executing. As JavaScript can alter the DOM or CSSOM the browser pauses building, known as &amp;quot;render blocking&amp;quot;.&lt;/p&gt;
&lt;p&gt;JavaScript cannot run until the CSSOM is built so will wait for it before executing.&lt;/p&gt;
&lt;p&gt;Adding the async property to a &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag means it will download in parallel with the document and execute as soon as it is available.&lt;/p&gt;
&lt;p&gt;Adding the defer property to a &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag means it will download in parallel with the document but only execute once the DOM and CSSOM have been created. It executes before the DOMContentLoaded event is fired. JavaScript modules are deferred automatically.&lt;/p&gt;
&lt;p&gt;If JavaScript alters the DOM or CSSOM then the browser has to go through some of the rendering steps again.&lt;/p&gt;
&lt;h2&gt;Problems&lt;/h2&gt;
&lt;p&gt;Any render blocking slows things down. This can be HTML or CSS that is not needed for the initial page load or JavaScript that causes rendering to wait.&lt;/p&gt;
&lt;p&gt;JavaScript that uses an internet connection, e.g. a fetch(), slows things down much more as the page has to wait for the response and the script execution to finish before rendering can continue.&lt;/p&gt;
&lt;p&gt;Trying to run scripts before all CSS has loaded and created the CSSOM results in scripts having to wait. Having large or multiple stylesheets increases this delay.&lt;/p&gt;
&lt;p&gt;If JavaScript loads CSS (common in packages) then the render has to wait for the JavaScript to finish executing, which in turn has to wait for the CSSOM to update. It&#39;s starting to queue up.&lt;/p&gt;
&lt;p&gt;The most common issue (in my opinion) is trying to load everything up front rather than using a well thought-out strategy to load content progressively as it is needed - designing for performance.&lt;/p&gt;
&lt;h2&gt;Critical Rendering Path (CRP) Optimisation&lt;/h2&gt;
&lt;p&gt;A Critical Rendering Path optimisation strategy enables a page to load as quickly as possible by prioritising resources and the order in which they are loaded.&lt;/p&gt;
&lt;h2&gt;Animation&lt;/h2&gt;
&lt;p&gt;A user&#39;s perception of an element moving is based on the speed at which the screen re-renders, the frame rate, measured in frames per second (fps). If an element jerks from one position to the next the illusion is broken, so it&#39;s important we can always re-render fast enough to avoid this.&lt;/p&gt;
&lt;h2&gt;User Interactions&lt;/h2&gt;
&lt;p&gt;When a user interacts with the UI, e.g. pressing a button or typing in a search box, then the UI needs to respond quickly so that the user does not feel a disconnect and that the UI is unresponsive. Ideally we should always acknowledge their interaction within 50ms. This does not have the be the completion of the action but we do need to confirm their interaction visually so that they don&#39;t question it, e.g. did they definitely press the button?&lt;/p&gt;
&lt;h2&gt;Tips&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Work out what is critical for the initial page load, load just that, and defer everything else. It does not have to be interactive. Sometimes just showing the user something is enough.&lt;/li&gt;
&lt;li&gt;Use preloading to get critical resources higher up the priority list, e.g. &lt;code&gt;&amp;lt;link rel=&amp;quot;preload&amp;quot; as=&amp;quot;script&amp;quot; href=&amp;quot;critical.js&amp;quot;&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Newer versions of webpack support preloading modules with &amp;quot;magic comments&amp;quot; in the import() statement, e.g. &lt;code&gt;import(_/* webpackPreload: true */_ &amp;quot;CriticalChunk&amp;quot;)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Good caching reduces response times and allows the various steps of rendering to start earlier.&lt;/li&gt;
&lt;li&gt;If you can, do any data binding needed for the initial page load server side then subsequent updates client side.&lt;/li&gt;
&lt;li&gt;Use the async or defer properties to execute scripts at the appropriate time.&lt;/li&gt;
&lt;li&gt;The HTML attribute &lt;code&gt;loading=&amp;quot;lazy&amp;quot;&lt;/code&gt; can be used with media (images, video, etc.) to tell the browser to only load the element when it enters the viewport.&lt;/li&gt;
&lt;li&gt;If you need to load data with JavaScript, e.g. a fetch(), do the initial page load so the user sees something, then get the data.&lt;/li&gt;
&lt;li&gt;Minimise changes to the DOM and CSSOM in scripts as it will mean the browser having to go through its steps again, a &amp;quot;reflow&amp;quot;.&lt;/li&gt;
&lt;li&gt;Avoid anything that changes layout (showing, hiding, resizing or repositioning) in scripts as layout is one of the slowest steps.&lt;/li&gt;
&lt;li&gt;Changes to colours, shadows and filters happen in the Paint step so are much faster. Only the last 2 steps have to be repeated.&lt;/li&gt;
&lt;li&gt;Changes using transform or opacity happen in the Composite step and only affect a single paint layer so mean minimal reflow.&lt;/li&gt;
&lt;li&gt;Animation should always try to avoid layout changes so use transform to move things, not width, left, margin, etc.&lt;/li&gt;
&lt;li&gt;The CSS will-change property tells the browser that an element is liable to change its appearance and to give it its own paint layer, so it can be redrawn in isolation without redrawing everything else. This is only needed if it&#39;s not already obvious from other rules like animation or transform.&lt;/li&gt;
&lt;li&gt;The CSS content-visibility: auto rule tells the browser to only render the element if it is near the viewport, so in a long page it can skip later content, e.g. a footer, to render the page faster.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Useful Links&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://developers.google.com/web/fundamentals/performance/critical-rendering-path&quot;&gt;Critical Rendering Path | Web Fundamentals | Google Developers&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://web.dev/preload-critical-assets/&quot;&gt;Preload critical assets to improve loading speed (web.dev)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://web.dev/optimize-webfont-loading/&quot;&gt;Optimize WebFont loading and rendering&lt;/a&gt;&lt;/p&gt;
</description>
      <pubDate>Sun, 30 Apr 2023 16:30:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2023/ui-performance-critical-rendering-path-optimisation/</guid>
    </item>
    <item>
      <title>CARPET - A Front End Checklist</title>
      <link>https://chrissmith.xyz/blog/2022/carpet-a-front-end-checklist/</link>
      <description>&lt;p&gt;The 6 areas to consider spell out &lt;strong&gt;CARPET&lt;/strong&gt;, hopefully making it easier to remember.&lt;/p&gt;
&lt;h3 id=&quot;Is-it-Clear?&quot;&gt;&lt;strong&gt;Is it Clear?&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;&lt;li&gt;Is it obvious what to do? Imagine it’s the user’s first day. Is help text needed?&lt;/li&gt;&lt;li&gt;If we include help text does it use plain English (or translated equivalent)?&lt;/li&gt;&lt;li&gt;Does any button text accurately reflect what will happen when it is pressed?&lt;/li&gt;&lt;/ul&gt;
&lt;h3 id=&quot;Is-it-Accessible?&quot;&gt;&lt;strong&gt;Is it Accessible?&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;&lt;li&gt;Are we using semantic HTML elements so the role of each piece of content is clear?&lt;/li&gt;&lt;li&gt;Is all text easily legible – large enough with enough contrast? If you have to think about it, probably not.&lt;/li&gt;&lt;li&gt;Do we have text descriptions for any visual media, such as images and icons?&lt;/li&gt;&lt;/ul&gt;
&lt;h3 id=&quot;Is-it-Responsive?&quot;&gt;&lt;strong&gt;Is it Responsive?&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;&lt;li&gt;Is it still usable when the viewport is very large or very small?&lt;/li&gt;&lt;li&gt;Do items that are visually grouped become disassociated when the screen is very wide?&lt;/li&gt;&lt;li&gt;Could the experience be optimised for different screen sizes?&lt;/li&gt;&lt;/ul&gt;
&lt;h3 id=&quot;Is-it-Performant?&quot;&gt;&lt;strong&gt;Is it Performant?&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;&lt;li&gt;Are there barriers which may mean waiting times greater than 2 seconds?&lt;/li&gt;&lt;li&gt;Are we keeping DOM manipulations to a minimum?&lt;/li&gt;&lt;li&gt;Could it be made faster, possibly by doing less at once, or doing some things in the background or asynchronously?&lt;/li&gt;&lt;/ul&gt;
&lt;h3 id=&quot;Is-it-Efficient?&quot;&gt;&lt;strong&gt;Is it Efficient?&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;&lt;li&gt;Is there user effort that we could remove - repetition of actions, excessive clicks or scrolling?&lt;/li&gt;&lt;li&gt;When the page loads is the initial focus on the most useful element?&lt;/li&gt;&lt;li&gt;Is there an opportunity to remember user preferences or persist filters?&lt;/li&gt;&lt;/ul&gt;
&lt;h3 id=&quot;Is-it-Testable?&quot;&gt;&lt;strong&gt;Is it Testable?&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;&lt;li&gt;Are any values that we may want to test available in the DOM?&lt;/li&gt;&lt;li&gt;Do elements with testable values have IDs or classes so that the specific elements can be targeted?&lt;/li&gt;&lt;li&gt;If we have values embedded in images, videos or canvas do we have a text equivalent which we can test?&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
</description>
      <pubDate>Fri, 08 Jul 2022 08:28:07 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2022/carpet-a-front-end-checklist/</guid>
    </item>
    <item>
      <title>How I&#39;d Learn Front End Web Development Now</title>
      <link>https://chrissmith.xyz/blog/2022/how-id-learn-front-end-web-development-now/</link>
      <description>&lt;p&gt;When I started out with doing web stuff in 1999, things were very different, much simpler in some ways but much harder in others. So, the way I gradually learnt was quite different from how somebody would learn now.&lt;/p&gt;
&lt;h2&gt;Back in my day...&lt;/h2&gt;
&lt;p&gt;Don&#39;t yawn, there is a point to this. In 1999 when I started learning this stuff, there was only HTML, CSS and JavaScript. No TypeScript, no Sass, no real frameworks to speak of, no packages, no build tools. You get the picture.&lt;/p&gt;
&lt;p&gt;So, there was a lot less to learn but learning was harder. There wasn&#39;t great documentation online, or, at least, not easy to find, so I used books. Cross browser compatibility was hard.&lt;/p&gt;
&lt;p&gt;In short, it&#39;s a completely different landscape now. So, I thought it would be interesting to think about how I would learn or advise others to learn if starting out now.&lt;/p&gt;
&lt;h2&gt;The basics&lt;/h2&gt;
&lt;p&gt;The basics are still the basics. &lt;strong&gt;HTML&lt;/strong&gt;, &lt;strong&gt;CSS&lt;/strong&gt; and &lt;strong&gt;JavaScript&lt;/strong&gt; are the technologies used by web browsers. That hasn&#39;t changed in all this time and it&#39;s not likely to change any time soon. While trends will come and go a good understanding of these three areas will always be time well spent.&lt;/p&gt;
&lt;h2&gt;Accessibility&lt;/h2&gt;
&lt;p&gt;This is a critical area that is often overlooked. The web is a universal platform that should be for everyone, not just for those with good eyesight, expensive devices and fast networks. We need to consider how we deliver content that works for all.&lt;/p&gt;
&lt;p&gt;It&#39;s definitely worth learning this from the beginning so things are done in the right way as it&#39;s harder to correct bad habits later. Being able to demonstrate an understanding of accessibility will put you ahead of other candidates who have skipped over it when it comes to job hunting.&lt;/p&gt;
&lt;h2&gt;Go deep&lt;/h2&gt;
&lt;p&gt;Going further, I&#39;d say it&#39;s worth exploring these HTML, CSS and JavaScript in some depth before moving on. I think it&#39;s worth skimming through everything on them at pace without worrying about retaining too much. This could be either a course or just working through documentation. Just becoming familiar with what features there are and some terminology will help you understand more conversations and documentation, as well as know what to search for when the time comes to use them. Nobody can remember it all and even experienced developers have to look up syntax. That&#39;s not generally what an employer would expect, it&#39;s more about the broad understanding of how you can use features to solve problems.&lt;/p&gt;
&lt;h2&gt;Responsive design&lt;/h2&gt;
&lt;p&gt;It&#39;s rare these days that we can create a web page that will be for a single screen size, so we need to know how to make a user interface that looks good on a big desktop screen and a phone. This is a whole area that is again worth tackling fairly early on. It&#39;s a bit of an art, a collection of techniques and tricks that are not easy to discover. This is an area that would probably benefit from a course.&lt;/p&gt;
&lt;h2&gt;Source control and package management&lt;/h2&gt;
&lt;p&gt;Once you&#39;ve got enough of the basics to make something amazing, you&#39;ll naturally want to share it with the world, and then you&#39;ll want to make use of your amazing thing or other people&#39;s in your future projects.&lt;/p&gt;
&lt;p&gt;Source control is about publishing code but also collaboration - reviewing each other&#39;s code, branching out and merging it back together. The most commonly used system for this is probably &lt;a href=&quot;https://git-scm.com/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;git&lt;/a&gt;. Worth reading up on.&lt;/p&gt;
&lt;p&gt;Package management is about bundling up your project into a package that can be easily exported and then imported into other projects. The most common platform for front end code is &lt;a href=&quot;https://www.npmjs.com/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot; title=&quot;npm&quot;&gt;npm&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;These two areas usually involve using the command line, a terminal where you type commands to make things happen. It&#39;s not as scary as it looks and makes you look like a proper hacker to those not in the know.&lt;/p&gt;
&lt;h2&gt;Frameworks&lt;/h2&gt;
&lt;p&gt;Probably later than some would expect, but I genuinely feel the other things are more important to get good longer term. If you learn a &lt;a href=&quot;https://chrissmith.xyz/blog/when-to-reach-for-a-framework-and-when-not-to/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;framework&lt;/a&gt; too early their way of doing things becomes your normal and then if you change framework you have to start again. If you understand the core technologies then you can see what the framework is giving you and can adjust more easily.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://chrissmith.xyz/blog/why-its-still-worth-learning-bootstrap/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;CSS frameworks&lt;/a&gt; can be very useful for providing ready-made styling, bringing consistency and the CSS is well structured. It&#39;s a good way of learning how to structure your own CSS for larger projects.&lt;/p&gt;
&lt;p&gt;JavaScript frameworks like &lt;a href=&quot;https://reactjs.org/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;React&lt;/a&gt;, &lt;a href=&quot;https://vuejs.org/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Vue&lt;/a&gt; or &lt;a href=&quot;https://angular.io/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Angular&lt;/a&gt; take some investment to learn but it is paid off in terms of faster development down the line.&lt;/p&gt;
&lt;p&gt;There are also UI frameworks and design systems which provide complete components ready to use.&lt;/p&gt;
&lt;p&gt;With all of these frameworks, there&#39;s lots of time saving and knowledge to be gained but it&#39;s important to remember that these are just someone&#39;s opinion and one way of doing things. There is no single right way or best way.&lt;/p&gt;
&lt;h2&gt;Extending the basics with pre-compilation&lt;/h2&gt;
&lt;p&gt;I&#39;d say that&#39;s probably everything you &lt;em&gt;need&lt;/em&gt; but there are a couple of other bits that are cheap to learn so worth throwing in there - more skills to boast about can&#39;t hurt.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://sass-lang.com/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Sass&lt;/a&gt; is a superset of CSS - it&#39;s CSS with added bells and whistles. You write in .scss files, making use of the fancy additional features and then it gets compiled to normal CSS. The great part is that it&#39;s additional features, not a different language so CSS is valid Sass. You can start out with a .scss file, just write normal CSS and it gets compiled to CSS. It&#39;s a bit pointless but means you can start off with nothing and then gradually learn and use Sass one feature at a time. It&#39;s a nice easy learning curve.&lt;/p&gt;
&lt;p&gt;It&#39;s the same idea with &lt;a href=&quot;https://www.typescriptlang.org/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;TypeScript&lt;/a&gt;. This is enhanced JavaScript so you can write in .ts files and get JavaScript, learning the new features as you go.&lt;/p&gt;
&lt;p&gt;With both of these, once you get into the new features you&#39;ll never go back.&lt;/p&gt;
&lt;h2&gt;Then, anything goes&lt;/h2&gt;
&lt;p&gt;Once you&#39;ve got these skills, it&#39;s really an open playing field. You can learn whatever takes your interest, or maybe whatever your job needs.&lt;/p&gt;
&lt;p&gt;Let me know if you&#39;d do things differently.&lt;/p&gt;
</description>
      <pubDate>Fri, 27 May 2022 16:30:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2022/how-id-learn-front-end-web-development-now/</guid>
    </item>
    <item>
      <title>Emmet - Write HTML and CSS Faster</title>
      <link>https://chrissmith.xyz/blog/2021/emmet-write-html-and-css-faster/</link>
      <description>&lt;h2&gt;What is Emmet?&lt;/h2&gt;
&lt;p&gt;Emmet is a productivity tool for HTML and CSS editors. It enables the author to type a shortcut and hit the TAB key to replace it with a predefined chunk of code called a &amp;quot;snippet&amp;quot;. It is already included in Visual Studio and VS Code by default, no extensions or packages needed. It does require knowledge of HTML tags and CSS selectors.&lt;/p&gt;
&lt;p&gt;In HTML, typing &lt;code&gt;a&lt;/code&gt; then hitting TAB gives &lt;code&gt;&amp;lt;a href=&amp;quot;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&lt;/code&gt; with the cursor placed ready between the href quotes.&lt;/p&gt;
&lt;p&gt;In CSS, typing &lt;code&gt;bgc&lt;/code&gt; then hitting TAB expands out to &lt;code&gt;background-color: #fff&lt;/code&gt; with the colour highlighted to be overwritten.&lt;/p&gt;
&lt;h2&gt;Default Snippets&lt;/h2&gt;
&lt;p&gt;Most of the shortcuts and snippets can be found on the official cheat sheet.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.emmet.io/cheat-sheet/&quot;&gt;Cheat Sheet (emmet.io)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The full list of default shortcuts and snippets in JSON format can be found on the Emmet GitHub repo:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/emmetio/snippets/blob/master/html.json&quot;&gt;Default HTML Snippets (GitHub)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/emmetio/snippets/blob/master/css.json&quot;&gt;Default CSS Snippets (GitHub)&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Custom Snippets&lt;/h2&gt;
&lt;p&gt;You can also extend this tool and create your own. This works differently in Visual Studio and VS Code but essentially you define your shortcut and snippet to output in either XML or JSON.&lt;/p&gt;
&lt;p&gt;In Visual Studio 2019, the option is under Tools &amp;gt; Code Snippets Manager. Each snippet is defined as a new XML file with extension .snippet. The easiest way to set this up is to copy one of the default files to get the XML structure, change it to what you need and then add/import it. This functionality can actually be used for any language.&lt;/p&gt;
&lt;p&gt;It’s a similar idea in VS Code but all of the snippets are stored in a single JSON file. This article explains it clearly. &lt;a href=&quot;https://www.smashingmagazine.com/2021/06/custom-emmet-snippets-vscode/&quot;&gt;Creating Custom Emmet Snippets In VS Code — Smashing Magazine&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;More&lt;/h2&gt;
&lt;p&gt;Emmet can also do larger scale boilerplates. Try typing &lt;code&gt;html:5&lt;/code&gt; then TAB in a new blank .html file. It creates a whole skeleton document structure.&lt;/p&gt;
&lt;p&gt;It also does Lorem Ipsum placeholder text. Type &lt;code&gt;lorem50&lt;/code&gt; then TAB and you get 50 words of Lorem Ipsum. This can be combined with tags, e.g. &lt;code&gt;p*4&amp;gt;lorem&lt;/code&gt;, to give quick placeholder content.&lt;/p&gt;
</description>
      <pubDate>Fri, 10 Dec 2021 17:15:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2021/emmet-write-html-and-css-faster/</guid>
    </item>
    <item>
      <title>Progress Indicators</title>
      <link>https://chrissmith.xyz/blog/2021/progress-indicators/</link>
      <description>&lt;p&gt;I&#39;ve been working on a questionnaire with a requirement to show progress through the questions. It has thrown up some interesting challenges which I felt were worth sharing.&lt;/p&gt;
&lt;p&gt;When I first saw the requirement I thought it would be simple - progress is just number of questions divided by number of answers, easy maths, right? Well, it could be in a very simple questionnaire but ours threw up a few more curved balls. Here are some additional considerations:&lt;/p&gt;
&lt;p&gt;Some questions are mandatory, others are optional, so are we counting all questions or only the mandatory ones?&lt;/p&gt;
&lt;p&gt;There is some conditional logic so a question may be shown or hidden depending on how you answer another question. How do we handle that?&lt;/p&gt;
&lt;p&gt;Some questions can have multiple answers, like a checkbox list, so how many do we count?&lt;/p&gt;
&lt;p&gt;Some answers may automatically answer other questions. I know this sounds odd but it&#39;s a big old questionnaire and sometimes it was useful to repeat some questions and answers in a different context in case it changed the answer.&lt;/p&gt;
&lt;p&gt;Our architecture has questions and answers as 2 separate API calls, which each bring back object arrays. Questions and answers are linked by a common data point, which is just an identifier so that we can match them up. So, time to work through our extra considerations...&lt;/p&gt;
&lt;p&gt;We only want to count mandatory questions. These are denoted by an isRequired property on each question so we can filter to that like this:&lt;/p&gt;
&lt;pre class=&quot;wp-block-code&quot;&gt;&lt;code&gt;const filteredQuestions = questions.filter(q =&amp;gt; q.isRequired);&lt;/code&gt;&lt;/pre&gt;
&lt;!-- /wp:code --&gt;
&lt;p&gt;We also only want to count questions that are shown. We can&#39;t reasonably expect a user to answer a question they haven&#39;t seen. This is similar to the isRequired property but using isVisible, so to filter on both of these (instead of just the one property above) we can do this:&lt;/p&gt;
&lt;pre class=&quot;wp-block-code&quot;&gt;&lt;code&gt;const filteredQuestions = questions.filter(q =&amp;gt; q.isRequired &amp;amp;&amp;amp; q.isVisible);&lt;/code&gt;&lt;/pre&gt;
&lt;!-- /wp:code --&gt;
&lt;p&gt;If questions have multiple answers, it doesn&#39;t matter, we&#39;re just interested in whether or not they have an answer.&lt;/p&gt;
&lt;p&gt;Next we need to deal with duplicated questions and/or answers. We can convert our filtered questions and our answers into arrays of unique data points. First we simplify the array to only hold the data point string, then we dedupe it by converting the array to a set and back again.&lt;/p&gt;
&lt;pre class=&quot;wp-block-code&quot;&gt;&lt;code&gt;const questionDataPoints = questions.map(q =&amp;gt; q.dataPoint);
const uniqueQuestionDataPoints = &amp;#91;...new Set(questionDataPoints)];

const answerDataPoints = answers.map(a =&amp;gt; a.dataPoint);
const uniqueAnswerDataPoints = &amp;#91;...new Set(answerDataPoints)];&lt;/code&gt;&lt;/pre&gt;
&lt;!-- /wp:code --&gt;
&lt;p&gt;Now that we&#39;ve got a list of unique question data points and a list of unique answer data points we only need to see which of our questions have answers, which we can do like this:&lt;/p&gt;
&lt;pre class=&quot;wp-block-code&quot;&gt;&lt;code&gt;const numberOfQuestions = uniqueQuestionDataPoints.length;
const questionsAnswered = uniqueQuestionDataPoints.filter(q =&amp;gt; uniqueAnswerDataPoints.includes(q));
const numberOfAnswers = questionsAnswered.length;&lt;/code&gt;&lt;/pre&gt;
&lt;!-- /wp:code --&gt;
&lt;p&gt;These figures can now be used as our value and max attributes or numerator and denominator in a fraction. To give a percentage we can do this:&lt;/p&gt;
&lt;pre class=&quot;wp-block-code&quot;&gt;&lt;code&gt;const percentage = Math.round((numberOfAnswers/numberOfQuestions) * 100);&lt;/code&gt;&lt;/pre&gt;
&lt;!-- /wp:code --&gt;
&lt;p&gt;If we want a normalised figure, a decimal in the range between 0 and 1, we can stick with the simpler fraction calculation like this:&lt;/p&gt;
&lt;pre class=&quot;wp-block-code&quot;&gt;&lt;code&gt;const normalized = numberOfAnswers/numberOfQuestions;&lt;/code&gt;&lt;/pre&gt;
&lt;!-- /wp:code --&gt;
&lt;p&gt;The &amp;lt;progress&amp;gt; HTML element can take max and value attributes or if we don&#39;t specify a max we can simply pass a normalised value.&lt;/p&gt;
</description>
      <pubDate>Sun, 23 May 2021 20:05:25 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2021/progress-indicators/</guid>
    </item>
    <item>
      <title>New Image Formats - WebP and AVIF</title>
      <link>https://chrissmith.xyz/blog/2021/new-image-formats-webp-and-avif/</link>
      <description>&lt;p&gt;Performance tools like Lighthouse now suggest using newer formats for images in place of the traditional JPG, PNG and GIF. Smaller file sizes mean faster load times for users and less storage space on servers.&lt;/p&gt;
&lt;h3&gt;Image Compression&lt;/h3&gt;
&lt;p&gt;Lossy compression means that as the image is reduced in size info is thrown away giving big savings on file size. If we take a 400x400 image and save it as 100x100, then resizing back up leads to pixilation.&lt;/p&gt;
&lt;p&gt;Lossless compression is the opposite, it retains the original info so we can resize back up.&lt;/p&gt;
&lt;h2&gt;WebP&lt;/h2&gt;
&lt;p&gt;This format was created by Google when they acquired a company specialising in this technology. WebP supports an alpha channel (transparency).&lt;/p&gt;
&lt;h3&gt;File Size Comparison&lt;/h3&gt;
&lt;p&gt;On average, Google estimates that WebP lossy compression results in files that are between 25% and 34% smaller than JPGs of the same quality.&lt;/p&gt;
&lt;p&gt;On average, Google estimates that WebP lossless compression results in files that are roughly 26% smaller than PNGs of the same quality.&lt;/p&gt;
&lt;p&gt;Google estimates the average reduction to be about 64% of the original size of a GIF when using lossy compression and 19% when using lossless.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;WebP (lossless)&lt;/th&gt;
&lt;th&gt;WebP (lossy)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;JPG&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;25-34% smaller&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PNG&lt;/td&gt;
&lt;td&gt;26% smaller&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GIF&lt;/td&gt;
&lt;td&gt;19% smaller&lt;/td&gt;
&lt;td&gt;64% smaller&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Browser Support&lt;/h3&gt;
&lt;p&gt;Support is good, pretty much all but IE. Safari is limited to macOS 11 Big Sur and later.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://caniuse.com/?search=webp&quot;&gt;https://caniuse.com/?search=webp&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We could offer users WebP with a JPG fallback using the &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; element but this means hosting 2 file formats.&lt;/p&gt;
&lt;h3&gt;Conversion&lt;/h3&gt;
&lt;p&gt;There are lots of options to convert JPG to WebP. We can do it server side with a NuGet package or client side in Node or using gulp or webpack. It can also be done via command line or an image editor. The [Squoosh app(https://squoosh.app/)] is excellent for any image conversion.&lt;/p&gt;
&lt;h2&gt;AVIF&lt;/h2&gt;
&lt;p&gt;This format is based on the .avi video format. It supports an alpha channel (transparency).&lt;/p&gt;
&lt;h3&gt;File Size Comparison&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;AVIF&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;JPG&lt;/td&gt;
&lt;td&gt;76% smaller*&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PNG&lt;/td&gt;
&lt;td&gt;47% smaller*&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WebP&lt;/td&gt;
&lt;td&gt;58% smaller*&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;* These figures are arrived at by manually editing images, finding acceptable quality and manually reducing palette sizes. As a bulk automated process there would be less of a saving, probably much closer to using WebP.&lt;/p&gt;
&lt;h3&gt;Browser Support&lt;/h3&gt;
&lt;p&gt;This is pretty much just Chrome for now but coming to Firefox and Edge soon. Something to monitor.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://caniuse.com/?search=avif&quot;&gt;https://caniuse.com/?search=avif&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We could offer users AVIF with WebP and JPG as fallback options using the &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; element but this means hosting multiple file formats.&lt;/p&gt;
&lt;h3&gt;Conversion&lt;/h3&gt;
&lt;p&gt;As with WebP there are tools to convert server side or client side.&lt;/p&gt;
&lt;p&gt;Encoding a JPG to AVIF is still quite slow compared with other image format conversions, taking a few seconds, so it&#39;s preferable to do as a background task rather than asking a user to wait for a response.&lt;/p&gt;
&lt;h2&gt;User Experience&lt;/h2&gt;
&lt;p&gt;The way the various image formats render differs. JPG appears quickly and renders in multiple passes. WebP renders from top to bottom. AVIF is all or nothing.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://jakearchibald.com/2020/avif-has-landed/#progressive-rendering&quot;&gt;https://jakearchibald.com/2020/avif-has-landed/#progressive-rendering&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;SVG can have smaller file size but if it is made up of a lot of elements can use a lot more CPU to render.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Our largest use of images is in checks (QC) and inspections (GM) which use JPG photos. Once IE11 is out of support (17th August 2021) the WebP format will have full browser support and could offer us consistent file size reductions of around 30%. AVIF does not yet have the support but has potential to push this further in the future.&lt;/p&gt;
&lt;p&gt;WebP is probably a good option for our online Marketing content (e.g. website) where images are selected and optimised manually.&lt;/p&gt;
&lt;h2&gt;Articles&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.smashingmagazine.com/2019/10/speed-up-your-website-webp/&quot;&gt;https://www.smashingmagazine.com/2019/10/speed-up-your-website-webp/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.smashingmagazine.com/2018/07/converting-images-to-webp/&quot;&gt;https://www.smashingmagazine.com/2018/07/converting-images-to-webp/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://jakearchibald.com/2020/avif-has-landed/&quot;&gt;https://jakearchibald.com/2020/avif-has-landed/&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Tools&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://squoosh.app/&quot;&gt;https://squoosh.app/&lt;/a&gt;&lt;/p&gt;
</description>
      <pubDate>Wed, 27 Jan 2021 17:30:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2021/new-image-formats-webp-and-avif/</guid>
    </item>
    <item>
      <title>Transitioning to Modern JavaScript</title>
      <link>https://chrissmith.xyz/blog/2021/transitioning-to-modern-javascript/</link>
      <description>&lt;p&gt;This is the title of a video from the December 2020 Chrome Dev Summit.
&lt;a href=&quot;https://www.youtube.com/watch?v=cLxNdLK--yI&quot;&gt;https://www.youtube.com/watch?v=cLxNdLK--yI&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Below is a summary of the main points from the video.&lt;/p&gt;
&lt;p&gt;&amp;quot;Modern&amp;quot; JavaScript is defined as JavaScript supported in modern browsers. Basically all but IE11.&lt;/p&gt;
&lt;h2&gt;Problems&lt;/h2&gt;
&lt;p&gt;On average, 95% of users use a modern browser, so we should ship modern code, not legacy just because we have to support the 5%.&lt;/p&gt;
&lt;p&gt;Most JavaScript code is transpiled so the code we write is not the same as the code we ship.&lt;/p&gt;
&lt;p&gt;On average, the code we ship is 6x slower and 7x larger than the code we write. This is down to longer syntax and polyfills. This inefficiency means we create a much greater carbon footprint.&lt;/p&gt;
&lt;p&gt;Most websites ship around 89% third party code, mainly NPM packages.&lt;/p&gt;
&lt;p&gt;Examining the top 1000 modules on npm, the median version is ES5 (legacy, pre 2015).
Some packages offer modern and legacy versions but less than 25% offer anything above ES5.&lt;/p&gt;
&lt;p&gt;So, we&#39;re working to the lowest common denominator and degrading performance for the majority.&lt;/p&gt;
&lt;h2&gt;Solutions&lt;/h2&gt;
&lt;p&gt;ES2019 introduced the &amp;quot;exports&amp;quot; property in packages so we can use this for modern code and the traditional &amp;quot;main&amp;quot; property for legacy code, like this:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// package.json&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;amaze-js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;exports&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./modern.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;main&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./legacy.js&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;ES2017 added modules so we can use this to separate modern and legacy scripts.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- ES2017 (95% support) --&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;module&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;modern.js&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- ES5 (+5% remaining) --&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;nomodule&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;legacy.js&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Of the versions since ES5, ES2017 gives the best compromise between modern features and compatibility, giving us 95% support. Therefore, the advice of the Chrome team is to transpile twice, creating separate bundles for ES2017 and ES5.&lt;/p&gt;
</description>
      <pubDate>Tue, 05 Jan 2021 17:00:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2021/transitioning-to-modern-javascript/</guid>
    </item>
    <item>
      <title>Learning to Write Code that is Good Enough</title>
      <link>https://chrissmith.xyz/blog/2020/learning-to-write-code-that-is-good-enough/</link>
      <description>&lt;p&gt;When you go through school you&#39;re always taught to do your best, to try to make the thing you&#39;re working on the best it can possibly be. When it comes to software we naturally want the same - we dream of something that&#39;s fast, accessible, responsive and free from any bugs. It&#39;s just not realistic.&lt;/p&gt;
&lt;h3&gt;Need for Speed&lt;/h3&gt;
&lt;p&gt;In the real world of web or software development, speed of development is key. We have to deliver functionality by deadlines. This might be because users need it for a fixed date, or maybe you need to move quickly to make the most of a gap in the market, or you need to beat your competitors or keep pace with them - there are many reasons.&lt;/p&gt;
&lt;p&gt;Let&#39;s say we&#39;re adding a new feature to search and filter product data. We&#39;ve estimated that the full feature will take 4 weeks. However, we can deliver a very basic search box that just matches all product text within a week. We can actually deliver about three quarters of the value to the end user in one quarter of the time.&lt;/p&gt;
&lt;p&gt;The need for speed means that we can&#39;t take our time and build the perfect solution. We need to be fast and that inevitably means compromising and cutting corners. It&#39;s OK to release something that isn&#39;t perfect. It&#39;s even OK to release something with known bugs.&lt;/p&gt;
&lt;h3&gt;Release Early&lt;/h3&gt;
&lt;p&gt;By getting the code into production and letting users try it out earlier we can use their feedback to steer the rest of the feature. Maybe after the first release we realise that this is all they need and we don&#39;t need to build the rest? Maybe it&#39;s too slow in the real world and we need to go back and improve this before adding more complexity? Maybe the known bugs are not quite what we thought they were?&lt;/p&gt;
&lt;p&gt;This is general agile development, starting simple and building in iterations, and is largely about good planning and communication. We can apply the same kind of thinking to the coding.&lt;/p&gt;
&lt;h3&gt;Coding Shortcuts&lt;/h3&gt;
&lt;p&gt;Can we get away with a hard-coded list or a static JSON file for now instead of creating a new database table or API?&lt;/p&gt;
&lt;p&gt;Can we select defaults on dropdown lists or radio button groups so we don&#39;t have to add required validation?&lt;/p&gt;
&lt;p&gt;Can we use browser storage rather than writing to the database?&lt;/p&gt;
&lt;p&gt;Can a form just post key-value pairs to an email address to begin with while we&#39;re working on the database?&lt;/p&gt;
&lt;p&gt;We don&#39;t need polished design or animations until we know the solution is right.&lt;/p&gt;
&lt;p&gt;I&#39;m sure you get the idea. Not perfect, just good enough. Go fast, hit the deadline, listen to feedback and improve it when the pressure&#39;s off. If you&#39;re releasing something that you feel is risky do it under a &#39;BETA&#39; or &#39;Experimental&#39; flag so users know what to expect and it doesn&#39;t damage your reputation.&lt;/p&gt;
</description>
      <pubDate>Mon, 03 Aug 2020 17:27:12 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2020/learning-to-write-code-that-is-good-enough/</guid>
    </item>
    <item>
      <title>Reasons for Developers to Have a Blog</title>
      <link>https://chrissmith.xyz/blog/2020/reasons-for-developers-to-have-a-blog/</link>
      <description>&lt;p&gt;One thing I&#39;d definitely recommend to any new developers is to have your own blog. It&#39;s also a view I&#39;ve seen shared by a lot of experienced developers. But why?&lt;/p&gt;
&lt;h3&gt;How I Started&lt;/h3&gt;
&lt;p&gt;I&#39;ve had this WordPress blog up and running since summer 2008. I know. A long time. I had a small static website for about 5 years before that. For me it came out of necessity. I was doing freelance web design so needed somewhere to promote my services and showcase what I could do. I started writing articles as a way of creating fresh content in order to climb the search engine results listings. This certainly did not have an instant impact but over a long time I think it did make a difference.&lt;/p&gt;
&lt;p&gt;When I started writing articles I knew that nobody would be reading them. I&#39;m a realist and accepted that from day one. I was writing for myself. I still see it this way. It&#39;s for me and if it helps someone else, that&#39;s a bonus.&lt;/p&gt;
&lt;h3&gt;Knowledge Base&lt;/h3&gt;
&lt;p&gt;When I learn something interesting that I think is worth holding onto I write about it. It&#39;s a good way of helping to commit it to memory as well as creating an easy to find reference point to come back to.&lt;/p&gt;
&lt;p&gt;With anything of a technical nature, putting it into your own words and using your own mental models really helps you to fully understand it. It&#39;s a bit like the idea of learning by teaching. If you&#39;ve ever done a presentation you&#39;ll know that the preparation you do really helps strengthen your own knowledge of the subject.&lt;/p&gt;
&lt;h3&gt;Your Journey&lt;/h3&gt;
&lt;p&gt;A bit like keeping a diary having your own blog will let you see where you were a year ago, 5 years ago, ten years ago, or more. It&#39;s like a record of your own journey within the technology and the industry.&lt;/p&gt;
&lt;h3&gt;Show and Tell&lt;/h3&gt;
&lt;p&gt;However, in my opinion, these are not the best reasons for having a blog. I think that the best reason is having something to show for your time. By putting in some time to write, little and often, over time you build up a nice collection of your thoughts, ideas and opinions. You have evidence of what you&#39;re into and what you spend time thinking about.&lt;/p&gt;
&lt;p&gt;Put yourself in an interview situation, going for your dream developer job. You can show your blog and right there you have strong evidence that you are passionate about the subject and that you willingly invest time and effort in it. That has to count for a lot. It shows more commitment and serious intent than social media activity.&lt;/p&gt;
&lt;h3&gt;Writing Tips&lt;/h3&gt;
&lt;p&gt;You don&#39;t have to be good at writing. Even the best writers improve over time.  Keep going and you&#39;ll find your way.&lt;/p&gt;
&lt;p&gt;Don&#39;t beat yourself up if you haven&#39;t written for a while. Just do it as and when you want to. Don&#39;t force it and write about something you&#39;re not that bothered about just to get content.&lt;/p&gt;
&lt;p&gt;Similarly, don&#39;t feel it has to be long form and 1000 words every time. It&#39;s fine to just share an idea in a few sentences.&lt;/p&gt;
&lt;h3&gt;Self Hosting&lt;/h3&gt;
&lt;p&gt;Another recommendation with writing a blog is to host your own site so that you retain 100% ownership of your content. There are numerous tech blogging platforms (e.g. medium, dev.to) but owning your own content and having any traffic surges benefiting you rather than the platform is definitely worth it long term.&lt;/p&gt;
&lt;p&gt;If you do use a third party platform check out the export options. Can you get all your content out and move it elsewhere? It&#39;s good to be free to do what you want with your work.&lt;/p&gt;
&lt;h3&gt;WordPress&lt;/h3&gt;
&lt;p&gt;There are lots of blogging platforms and software options out there. Personally I&#39;ve always found WordPress is the best fit for my needs. The fact that it has native apps means that if I&#39;m out and about and suddenly have a great idea for a post I can capture a quick draft there and then.&lt;/p&gt;
&lt;p&gt;It&#39;s also very easy to export and import your data, meaning you can shift content from an old blog to a new one, combine or separate blogs, and move between hosted (.com) and self-hosted (.org) versions.&lt;/p&gt;
&lt;p&gt;The control over the design and ability to switch themes easily means you can keep your site fresh without having to worry about rewriting the content - there&#39;s a perfect separation between content and presentation.&lt;/p&gt;
</description>
      <pubDate>Sun, 26 Jul 2020 16:01:11 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2020/reasons-for-developers-to-have-a-blog/</guid>
    </item>
    <item>
      <title>The Dangers of Logic in CSS</title>
      <link>https://chrissmith.xyz/blog/2020/the-dangers-of-logic-in-css/</link>
      <description>&lt;p&gt;We can do a lot of logic in CSS. I&#39;m thinking specifically of scenarios which take the form &amp;quot;if this, then that&amp;quot;.&lt;/p&gt;
&lt;p&gt;There are media queries which will let us control the appearance of elements based on a variety of factors. Probably the most common is screen width, so we get things like &amp;quot;if the width is 1024px or higher, then show an extra element&amp;quot;.&lt;/p&gt;
&lt;p&gt;There are pseudo selectors like &lt;code&gt;:empty&lt;/code&gt;, &lt;code&gt;:checked&lt;/code&gt;, &lt;code&gt;:valid&lt;/code&gt;, &lt;code&gt;:disabled&lt;/code&gt; which let us control appearance based on state, giving us, for example, &amp;quot;if the parent element has no children (:empty), then change its opacity&amp;quot;.&lt;/p&gt;
&lt;p&gt;We can also do logic based on combinations of elements or selectors, like li + li, for example, &amp;quot;if the list item follows another list item, then give it a top border.&amp;quot;&lt;/p&gt;
&lt;p&gt;I&#39;m sure there are plenty more ways of applying logic but you get the idea. Each of these is equivalent to writing a conditional statement in a programming language - if this, then that.&lt;/p&gt;
&lt;p&gt;The big question is, should we be doing this in CSS, and is there a point at which it becomes too difficult to manage in CSS and we need to defer to another technology, like JavaScript?&lt;/p&gt;
&lt;h2&gt;My Experience&lt;/h2&gt;
&lt;p&gt;I started thinking about this when I was designing a UI with a lot of logic going on. We had a busy table where we show some additional columns at wider screen resolutions. At smaller widths the user would be able to toggle between different groups of columns and save a preference. But then these additional columns are only offered if they contain data. So, we had logic around the screen width, user preference and presence of data, which, multiplied out, meant 8 permutations.&lt;/p&gt;
&lt;p&gt;I initially tried to do it all with CSS. I set up media queries for the narrower and wider screen widths. Within each of these I then read a class for the user preference and then I used &lt;code&gt;:empty&lt;/code&gt; to see if table cells contained any data. I managed it and it worked. Just.&lt;/p&gt;
&lt;p&gt;However, I realised that it was really not scalable. Every time I added a new condition it doubled the amount of CSS I was having to write. If we wanted to add more logic in future it would create more and more work and be harder and harder to maintain.&lt;/p&gt;
&lt;p&gt;By moving all the logic into JavaScript we can set simpler classes, one for each type of display we need rather than every permutation of logic. So now we just have 3 classes: 1) show the first set of columns, 2) show the second set or 3) show all columns.&lt;/p&gt;
&lt;p&gt;We still have lots of branches in our JavaScript but the big difference is that it&#39;s easy to read and follow. It&#39;s also easy to edit or extend if we ever need to.&lt;/p&gt;
&lt;p&gt;I think doing some logic with CSS is fine but as soon as you&#39;re starting to layer it on and find yourself multiplying out the selectors you&#39;re writing it&#39;s probably time to move it over to JavaScript.&lt;/p&gt;
</description>
      <pubDate>Thu, 26 Mar 2020 18:00:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2020/the-dangers-of-logic-in-css/</guid>
    </item>
    <item>
      <title>Clicking Off Things to Close Them</title>
      <link>https://chrissmith.xyz/blog/2020/clicking-off-things-to-close-them/</link>
      <description>&lt;p&gt;There&#39;s a common design pattern these days where a bit of content is shown over the main screen. It might be a modal window or maybe a fly-in menu or sidebar. It&#39;s also common, especially in native apps, that we can just click or tap in the space not used by these elements to close them. So, how can we do this?&lt;/p&gt;
&lt;p&gt;I think there are 2 approaches, one which is pure JavaScript and another which involves an overlay element. Let&#39;s look at both.&lt;/p&gt;
&lt;h3&gt;JavaScript Document Click Event Method&lt;/h3&gt;
&lt;p&gt;We can detect that a click is not on the content element using JavaScript. As all click events bubble up or propagate through the DOM tree they eventually reach the top document level. We can listen for a click on the document and then use the event target to check what was clicked. For this example let&#39;s assume our content element has a class of &#39;modal&#39;, like &amp;lt;div class=&quot;modal&quot;&gt;&amp;lt;/div&gt;.&lt;/p&gt;
&lt;pre class=&quot;wp-block-code&quot;&gt;&lt;code&gt;// JavaScript

function handleClick(event) {
  if (!event.target.closest(&#39;.modal&#39;)) {
    console.log(&#39;close&#39;);
  }
}

document.addEventListener(&#39;click&#39;, handleClick);&lt;/code&gt;&lt;/pre&gt;
&lt;!-- /wp:code --&gt;
&lt;p&gt;event.target gets the element that was clicked. This could be the modal element itself, another element inside it or another element outside of it. event.target.closest(&#39;.modal&#39;) checks if the element clicked is the modal or is an antecedent of the modal element, an element within it. If the element clicked is not (!) in the modal we can close it.&lt;/p&gt;
&lt;p&gt;It&#39;s maybe worth noting that .closest() doesn&#39;t work in IE11 if you need to support this but there is a polyfill available.&lt;/p&gt;
&lt;h3&gt;Using an Overlay Element&lt;/h3&gt;
&lt;p&gt;The other approach, and the one I tend to use, is to use an overlay element. This means adding an element that covers the whole screen area, slipped in between the modal and the main screen content. The idea is that this overlay will appear and disappear along with the modal and will pick up any click events which are not on the modal. It&#39;s a bit like a safety net that will catch any stray clicks.&lt;/p&gt;
&lt;p&gt;The CSS for the overlay would typically look something like this:&lt;/p&gt;
&lt;pre class=&quot;wp-block-code&quot;&gt;&lt;code&gt;/* CSS */

.overlay {
  background-color:#000;
  bottom:0;
  left:0;
  opacity:.5;
  position:fixed;
  right:0;
  top:0;
  z-index:1;
}

.modal {
  /* styling */
  z-index:2;
}&lt;/code&gt;&lt;/pre&gt;
&lt;!-- /wp:code --&gt;
&lt;p&gt;The overlay has fixed display and goes to each edge so it fills the screen.&lt;/p&gt;
&lt;p&gt;The overlay has z-index set to 1 so it&#39;s over the main screen content, and the modal has it set to 2 so it&#39;s over the overlay. These can increase as needed but the modal always needs to be higher.&lt;/p&gt;
&lt;p&gt;I&#39;ve given the overlay a background colour and 50% (.5) opacity so that it veils the main screen content underneath giving the modal a &quot;lightbox&quot; effect but these are not needed and our overlay can be effectively invisible.&lt;/p&gt;
&lt;p&gt;You then just add a click event to the overlay which will close the modal and hide the overlay.&lt;/p&gt;
&lt;p&gt;The reason I like this approach is that by covering the main screen we prevent any interactions with it. If the user tries to click on a button under the overlay their first click will just close the modal. We don&#39;t need to worry about any other interactions - while the modal is showing it becomes the sole focus.&lt;/p&gt;
&lt;p&gt;Extra tip. If you use a visible overlay it&#39;s nicer not to show and hide it immediately but fade it in and out with a transition on the opacity, taking it between 0 and .5. This feels much smoother and less jerky.&lt;/p&gt;
</description>
      <pubDate>Wed, 25 Mar 2020 18:00:53 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2020/clicking-off-things-to-close-them/</guid>
    </item>
    <item>
      <title>Tips for Working from Home</title>
      <link>https://chrissmith.xyz/blog/2020/tips-for-working-from-home/</link>
      <description>&lt;p&gt;I&#39;ve been working from home 2 days a week for a few years so thought I&#39;d share a few tips. These are little things that work for me - they may not be for everyone.&lt;/p&gt;
&lt;h3&gt;Get Showered and Dressed&lt;/h3&gt;
&lt;p&gt;It sounds obvious but don&#39;t slouch around in your pyjamas. You need to make a work day different from the weekend and any little things you can do to create this clear separation will help your work-life balance and ensure you&#39;re in the right mindset, both ways.&lt;/p&gt;
&lt;h3&gt;Set Start and End Times&lt;/h3&gt;
&lt;p&gt;Don&#39;t try to be too flexible with your hours. Stick to a normal working day. Don&#39;t slack off and think you can catch up later in your own time, and don&#39;t do extra to overcompensate for being at home. You need clear times when work stops and home life starts. It&#39;s very easy to get sucked in to &quot;just finishing off this bit&quot; and still be working hours later.&lt;/p&gt;
&lt;h3&gt;Find Multiple Locations to Work&lt;/h3&gt;
&lt;p&gt;If you&#39;re working from home for several consecutive days it can help to vary where you work. I wouldn&#39;t keep moving in one day but maybe start every third day in a new spot. For some people having a fixed work space within their home helps the separation so if this works for you, great.&lt;/p&gt;
&lt;h3&gt;Finding a Good Work Space&lt;/h3&gt;
&lt;p&gt;For me it&#39;s important to be near a window. I actually work sitting in a bay window looking out onto my street. This naturally makes me look up from my screen from time to time as people pass by. My sleepy town isn&#39;t interesting enough for this to become a distraction but I appreciate this may not work somewhere busier. I would avoid spaces with no natural light, like lofts or basements. They&#39;re just not good for your state of mind.&lt;/p&gt;
&lt;h3&gt;Lunch&lt;/h3&gt;
&lt;p&gt;Set a start and end time for lunch as you would in an office environment. If you don&#39;t, you risk not finding time at all, not taking a break or the day becomes one continuous snack-fest, which is not going to end well over a sustained period of time.&lt;/p&gt;
&lt;h3&gt;Managing Costs&lt;/h3&gt;
&lt;p&gt;If you&#39;re home alone, do you really want to be heating your whole house? Or, if you&#39;re lucky enough to be somewhere warmer, using air-con? I try to stick to being in one room, close the door and use a portable heater. This saves a small fortune on my heating bill.&lt;/p&gt;
&lt;p&gt;Think about the money you&#39;re saving on travel and put it aside for something which improves your home working lifestyle - a comfy office chair, a desk fan, a fancy microphone, a coffee machine.&lt;/p&gt;
&lt;h3&gt;Balancing Non-work Activity&lt;/h3&gt;
&lt;p&gt;Working from home does bring some advantages. You can have goods delivered. You can have the washing machine or dishwasher going. My tip would be to not worry about the small things like answering the door, putting a load of washing on - things that take a trivial amount of time. You should avoid the tasks that take longer and can be left until after work - online shopping, folding washing, cooking.&lt;/p&gt;
&lt;h3&gt;Distractions&lt;/h3&gt;
&lt;p&gt;You&#39;re at work. You can ignore the door. You can ignore your phone. Don&#39;t use social media, unless it&#39;s work related.&lt;/p&gt;
&lt;h3&gt;Don&#39;t Get Isolated&lt;/h3&gt;
&lt;p&gt;If you&#39;re alone for a period of time it&#39;s easy to start to feel isolated. When working from home you need to make extra effort to communicate with colleagues. Try to make the effort to actually talk to people rather than just using email or messaging services like Slack. You won&#39;t run into colleagues in communal areas, like the office water cooler or kitchen, so, if a few of you are working remotely you may need to create your own virtual spaces where non work related chat can happen to stay connected on a human level.&lt;/p&gt;
&lt;h3&gt;What Works for You?&lt;/h3&gt;
&lt;p&gt;Everyone&#39;s different so do what works for you and if you have any good tips of your own please share.&lt;/p&gt;
</description>
      <pubDate>Sun, 15 Mar 2020 08:31:56 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2020/tips-for-working-from-home/</guid>
    </item>
    <item>
      <title>Print CSS Tips</title>
      <link>https://chrissmith.xyz/blog/2020/print-css-tips/</link>
      <description>&lt;p&gt;A collection of Print CSS problems and tips, learned the hard way...&lt;/p&gt;
&lt;p&gt;A common use of print CSS is for reporting, either printing HTML directly or using a tool to generate a PDF from HTML. HTML being written to PDF will be treated as print media rather than screen.&lt;/p&gt;
&lt;h2&gt;Page Breaks&lt;/h2&gt;
&lt;p&gt;We can control page breaks by setting rules on page elements, setting whether they should break before, after or avoid breaking - keep the content together. These are useful for starting a new section on a new page, keeping headings with their content or keeping related data together on a single page.&lt;/p&gt;
&lt;p&gt;Nice simple explanation:
&lt;a href=&quot;https://css-tricks.com/almanac/properties/p/page-break/&quot;&gt;https://css-tricks.com/almanac/properties/p/page-break/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The way this works is fairly straightforward but browser support is not consistent and different elements with different display types (e.g. block, inline, table, flex) are treated differently.&lt;/p&gt;
&lt;p&gt;Avoid complex layouts like display: grid, display: flex or display: table and use display: block wherever possible. It&#39;s worth considering an alternate, simplified, single stack layout for print.&lt;/p&gt;
&lt;h2&gt;Tables&lt;/h2&gt;
&lt;p&gt;Tables generally work as expected but some more advanced formatting can cause problems. If your table has &lt;code&gt;border-collapse: collapse&lt;/code&gt; set, which means cells are touching and sharing a border rather than spaced out with a gap between, then using rowspan or colspan to merge cells can lead to some of these shared borders going missing when printed.&lt;/p&gt;
&lt;p&gt;If you have to use spanning of rows or columns you can manually put borders back in by using CSS pseudo elements. You can create thin inner elements to act as borders, like this example (below) which adds a left border to all but the first cell.&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;th[rowspan] + th[rowspan],
td[rowspan] + td[rowspan]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; relative&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token selector&quot;&gt;th[rowspan] + th[rowspan]:before,
td[rowspan] + td[rowspan]:before&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;border-left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; solid 1px #000&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;bottom&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; -1px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; absolute&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;top&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Page Breaks and Tables&lt;/h2&gt;
&lt;p&gt;It&#39;s common for a table to exceed the length of a print page and need to break. If not handled right it can split rows or cells, which looks untidy and makes content difficult to read.&lt;/p&gt;
&lt;p&gt;To prevent this we would expect to use &lt;code&gt;page-break-inside: avoid&lt;/code&gt; on the &lt;code&gt;tr&lt;/code&gt; or &lt;code&gt;td&lt;/code&gt; elements but (at the time of writing, Jan 2020) this is not supported in most browsers. It is also not supported on the &lt;code&gt;thead&lt;/code&gt; or &lt;code&gt;tbody&lt;/code&gt; elements.&lt;/p&gt;
&lt;p&gt;We can also get an almost empty first page. The table content is so long that after the title it moves onto the second page leaving the first page with just the title. The solutions to both these issues are the same.&lt;/p&gt;
&lt;p&gt;Page break rules are supported on the table element or by wrapping the table element in a parent div element. So, rather than having lots of rows repeating within a single table we can use multiple tables, grouping rows in smaller tables or even using a new table for each row if absolutely necessary.&lt;/p&gt;
&lt;p&gt;Tables which are potentially very long need to dynamically split their content into smaller tables, e.g. table 1: rows 1-10; table 2: rows 11-20, etc.&lt;/p&gt;
&lt;p&gt;If you don’t have borders, just using spacing, then you can prevent your content from splitting over the page by wrapping the cell content in a div element, example below.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;tr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;td&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;your cell content&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;td&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;tr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Further Reading&lt;/h2&gt;
&lt;p&gt;This article gives a great explanation of print stylesheets:
&lt;a href=&quot;https://www.smashingmagazine.com/2018/05/print-stylesheets-in-2018/&quot;&gt;https://www.smashingmagazine.com/2018/05/print-stylesheets-in-2018/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This article explains fragmentation - handling breaks in pages and columns:
&lt;a href=&quot;https://www.smashingmagazine.com/2019/02/css-fragmentation/&quot;&gt;https://www.smashingmagazine.com/2019/02/css-fragmentation/&lt;/a&gt;&lt;/p&gt;
</description>
      <pubDate>Fri, 17 Jan 2020 16:00:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2020/print-css-tips/</guid>
    </item>
    <item>
      <title>Switching APIs</title>
      <link>https://chrissmith.xyz/blog/2019/switching-apis/</link>
      <description>&lt;p&gt;It&#39;s completely normal now for web apps to work with external third party JavaScript APIs. The good ones give you lots of documentation making them pretty straightforward to implement and use. You load a script from a URL or local resource, use their methods and properties in your code and away you go.&lt;/p&gt;
&lt;p&gt;But what if you then want to switch to another API provider? Maybe the one you were using isn&#39;t accessible, doesn&#39;t support the older browsers you need? Maybe they put their prices up? Whatever the reason you may need to switch at some point.&lt;/p&gt;
&lt;p&gt;This change means rewriting your app&#39;s JavaScript to work with the new API. You&#39;ll have to find every point it touches and update it. What if it works differently? What if this one takes an object parameter rather than an array? You&#39;ll have to completely rewrite the data parts too.&lt;/p&gt;
&lt;p&gt;There is a better way.&lt;/p&gt;
&lt;p&gt;Rather than working directly with an API and using the properties and methods in your code, you create an intermediary, your own internal service, which handles this functionality. The internal service maps the properties and methods you need to those of the third party API. It handles any data transformation needed. Your app works with this service, your own API, so that when a change of service provider is needed the app itself does not need to be rewritten, just the internal service.&lt;/p&gt;
&lt;p&gt;An internal service can also be set up to work with multiple APIs at once so it maps everything it needs for each. This allows you to push choice to your users. So, for example, if it&#39;s a news, sport or weather feed built into a site, you can let your user choice their preferred information source. You could use different services for different regions, e.g. local news.&lt;/p&gt;
&lt;p&gt;To use a slightly inappropriate analogy, it&#39;s better to be dating these APIs than to move in with them. &amp;#x1f609;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
</description>
      <pubDate>Thu, 17 Oct 2019 18:00:59 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2019/switching-apis/</guid>
    </item>
    <item>
      <title>Safer Passwords</title>
      <link>https://chrissmith.xyz/blog/2019/safer-passwords/</link>
      <description>&lt;p&gt;Just thought I&#39;d pass on a few tips that I&#39;ve been given for setting a password that won&#39;t get hacked.&lt;/p&gt;
&lt;p&gt;Passwords can be hacked in two ways - being guessed by a human or being &quot;brute forced&quot; by a computer. Brute forcing just means trying lots of different passwords until it succeeds and powerful computers can do &lt;em&gt;a lot&lt;/em&gt; in a short time.&lt;/p&gt;
&lt;h3&gt;Go Long&lt;/h3&gt;
&lt;p&gt;The more characters you use, the more possible combinations there are and the longer it would take a computer to crack. To keep it easy to remember but hard to crack, try using a few words. However, you should avoid any common combinations of words, such as well known song lyrics, which may be more guessable. Random, unconnected words are best.&lt;/p&gt;
&lt;h3&gt;How Secure is Secure?&lt;/h3&gt;
&lt;p&gt;You can actually get a measure of how secure your password is on the aptly named  &lt;a rel=&quot;noreferrer noopener&quot; aria-label=&quot;https://howsecureismypassword.net/ (opens in a new tab)&quot; href=&quot;https://howsecureismypassword.net/&quot; target=&quot;_blank&quot;&gt;https://howsecureismypassword.net/&lt;/a&gt;. This site will estimate how long it would take a computer to crack your password. You want this to be so long that it wouldn&#39;t be possible within your lifetime. You should ideally allow far longer than seems necessary as computers will inevitably become more powerful and faster over time. I&#39;d aim for at least a millennium (1000 years) but the longer the better.&lt;/p&gt;
&lt;h3&gt;Pwned? *&lt;/h3&gt;
&lt;p&gt;The final check is to see if your chosen password has been previously involved in a data breach. When companies&#39; user accounts are hacked, the usernames and passwords used are stored (not together) in a public database so they can be flagged as unsuitable for reuse in the future. The service  &lt;a rel=&quot;noreferrer noopener&quot; aria-label=&quot;https://haveibeenpwned.com/ (opens in a new tab)&quot; href=&quot;https://haveibeenpwned.com/&quot; target=&quot;_blank&quot;&gt;https://haveibeenpwned.com/&lt;/a&gt; allows you to check if your password is safe from being on hackers&#39; known password lists.&lt;/p&gt;
&lt;h3&gt;Pass It On&lt;/h3&gt;
&lt;p&gt;Please pass this info on to anyone and everyone so that we&#39;re all safer. Share or feel free to copy and reword the content of this post however you see fit, just get the message out there. No more Pa$$word1.&lt;/p&gt;
&lt;p&gt;* It looks like a weird typo but &#39;pwned&#39; just means hacked.&lt;/p&gt;
</description>
      <pubDate>Fri, 11 Oct 2019 13:30:48 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2019/safer-passwords/</guid>
    </item>
    <item>
      <title>Edging Out of IE Support</title>
      <link>https://chrissmith.xyz/blog/2019/edging-out-of-ie-support/</link>
      <description>&lt;p&gt;Having to support a minority of users on IE11 is painful. It&#39;s a browser that is still officially supported by Microsoft, until 2025, but active development has stopped, or at least slowed right down, so the gap between it and other browsers is growing wider with every update.&lt;/p&gt;
&lt;p&gt;The growing feature gap means either not using newer features if we&#39;re working to the lowest common denominator or else having to provide polyfills or fallbacks so IE11 can still be used.&lt;/p&gt;
&lt;p&gt;But there could be a light at the end of the tunnel, and before 2025. Microsoft Edge is moving from using the EdgeHTML engine to open source Chromium, which will bring it in line with Chrome, Opera and Safari. That&#39;s nice for compatibility but the big deal is that it will be available on older Windows operating systems. Up until now Edge was only available on Windows 10 but it will soon be available on 7, 8 and 8.1 too so more users can drop IE and use Edge as their official Microsoft browser.&lt;/p&gt;
&lt;p&gt;The Edge team are going one better than that though. One of the big reasons for clinging on to IE is the use of legacy software which only works on that browser. Edge is introducing an IE11 mode, so users can seamlessly (hmm - I can already hear the massive crash) switch over to IE for specific sites. Very clever.&lt;/p&gt;
&lt;p&gt;It looks like we might have a way out of IE11 support in the next 12 months or so. Just need to convince the large corporations to make the switch now but I&#39;m sure Microsoft will be pushing hard on this too. Good news.&lt;/p&gt;
</description>
      <pubDate>Sun, 04 Aug 2019 10:00:51 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2019/edging-out-of-ie-support/</guid>
    </item>
    <item>
      <title>Performance Perception Trick: Processing Lists Faster</title>
      <link>https://chrissmith.xyz/blog/2019/performance-perception-trick-processing-lists-faster/</link>
      <description>&lt;p&gt;I&#39;ve got a little trick to make the processing of lists appear to go faster than it actually does.&lt;/p&gt;
&lt;p&gt;Let&#39;s suppose we have a list of 10 items and there&#39;s some kind of processing to be done on them, maybe sending them off to a service which returns a Boolean true/false response for each. In reality we post a single request with the data of the 10 items and we get a single response back after 3 seconds.&lt;/p&gt;
&lt;p&gt;In the UI we can use animation to make it look as if each item is being sent one at a time by adding a 100 millisecond delay between each state change. This means that the user thinks the last item of the 10 is sent after 1 second but in reality it&#39;s already gone a second  ago buying us extra time.&lt;/p&gt;
&lt;p&gt;When we get the response, rather than show all the results immediately, we can use a similar animation to make them appear one by one with a 100 millisecond delay again. Although this is slower than just showing them all it maintains the illusion of the items being processed one by one.&lt;/p&gt;
&lt;p&gt;So, the reality, without the trickery, is like this:&lt;/p&gt;
&lt;table class=&quot;wp-block-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;inline-size:2em&quot;&gt;0&lt;/td&gt;&lt;td&gt;Request sent,&lt;br /&gt;perceived waiting time begins&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style=&quot;inline-size:2em&quot;&gt;3&lt;/td&gt;&lt;td&gt;Response returned,&lt;br /&gt;UI updated,&lt;br /&gt;perceived waiting time ends&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;This would mean a perceived waiting time of 3 seconds.&lt;/p&gt;
&lt;p&gt;And with the trickery:&lt;/p&gt;
&lt;table class=&quot;wp-block-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;inline-size:2em&quot;&gt;0&lt;/td&gt;&lt;td&gt;Request sent,&lt;br /&gt;animation started&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style=&quot;inline-size:2em&quot;&gt;1&lt;/td&gt;&lt;td&gt;Animation ends,&lt;br /&gt;perceived waiting time begins&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style=&quot;inline-size:2em&quot;&gt;3&lt;/td&gt;&lt;td&gt;Response returned,&lt;br /&gt;animation started,&lt;br /&gt;perceived waiting time ends&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style=&quot;inline-size:2em&quot;&gt;4&lt;/td&gt;&lt;td&gt;Animation ends&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Even though the time to getting the final bit of data on screen is actually extended to 4 seconds, the perceived waiting time is reduced to 2 seconds.&lt;/p&gt;
</description>
      <pubDate>Sat, 03 Aug 2019 08:00:23 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2019/performance-perception-trick-processing-lists-faster/</guid>
    </item>
    <item>
      <title>Should Designers Be Able to Code?</title>
      <link>https://chrissmith.xyz/blog/2019/should-designers-be-able-to-code/</link>
      <description>&lt;p&gt;This seems to be a bit of a hot topic on Twitter right now so here&#39;s my take.&lt;/p&gt;
&lt;p&gt;The definitions of designer and developer and where you draw the line between the roles is a bit of a nonsense. In reality you can&#39;t box things like this. It&#39;s about the individuals and what skills they have and what fits your team. Overlaps in skills are not a problem, gaps are. So, the handover points will naturally surface out of what works for the team. That said, I do have some more specific thoughts about what might kinds of coding might empower a designer.&lt;/p&gt;
&lt;p&gt;I&#39;m assuming we&#39;re talking about designers who already write HTML and CSS and what level of JavaScript they should know or learn. A designer who works in a graphics editor or prototyping environment clearly has a different skill set.&lt;/p&gt;
&lt;p&gt;Knowing some basic DOM manipulation techniques can really help to add some life and interaction to designs - &amp;quot;Interaction Design&amp;quot;.&lt;/p&gt;
&lt;ol&gt;
 	&lt;li&gt;Being able to select a DOM element with &lt;code&gt;document.querySelector()&lt;/code&gt; is a good starting point.&lt;/li&gt;
 	&lt;li&gt;Basic event handling with &lt;code&gt;.addEventListener(&#39;click&#39;, handler)&lt;/code&gt; is useful as it allows you to add actions.&lt;/li&gt;
 	&lt;li&gt;Handling events means learning how to write a very basic named function.&lt;/li&gt;
 	&lt;li&gt;Finally being able to toggle properties like &lt;code&gt;hidden&lt;/code&gt; and &lt;code&gt;disabled&lt;/code&gt; or add/remove/toggle items from &lt;code&gt;classList&lt;/code&gt; enables you to design for lots of different states within the same document.&lt;/li&gt;
&lt;/ol&gt;
I think just these few basic steps will enable a designer to achieve a lot more in their designs.
&lt;p&gt;Most beginner&#39;s JavaScript courses I&#39;ve seen seem to start with constructing objects but this is far less useful for UI work. Designers probably don&#39;t need to worry about objects, arrays, classes and the whole data side. Static data is generally sufficient for communicating the design and interactions.&lt;/p&gt;
</description>
      <pubDate>Fri, 02 Aug 2019 18:00:05 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2019/should-designers-be-able-to-code/</guid>
    </item>
    <item>
      <title>What Techies Tweet</title>
      <link>https://chrissmith.xyz/blog/2019/what-techies-tweet/</link>
      <description>&lt;p&gt;I was curious as to what value I was getting out of following people in the tech industry on Twitter. Are they sharing useful information or just sharing pictures of their pets? Is it jokes and memes, self-promotion, sharing useful resources, praise, criticism, politics? I studied &lt;strong&gt;100&lt;/strong&gt; consecutive tweets to get an idea.&lt;/p&gt;
&lt;p&gt;This is by knows means scientific but still quite interesting. There are a few important parameters for how I use Twitter, which may explain differences from what you see. Firstly, I don&#39;t exclusively follow people in tech. I follow real world friends, football journalists, comedians, celebrities - a pretty broad spectrum of people. Here I&#39;ve limited the tweets analysed to just those from people in tech. I&#39;ve got to admit there were one or two where I wasn&#39;t sure so had to check their bios. Secondly, I try to follow real people, not faceless organisations. My rationale is that organisations&#39; tweets are 99% self-promotion. If their content is good enough I&#39;ll get to hear about it via others retweeting. I&#39;m trusting the people I follow to filter the organisational information I receive. Final point is I have a couple of words muted - &quot;Trump&quot; and &quot;Brexit&quot;. This will obviously impact on the amount of political tweets I see.&lt;/p&gt;
&lt;p&gt;So, here&#39;s a breakdown from &lt;strong&gt;100&lt;/strong&gt; tweets on Friday 26th April, roughly 5.00 - 5.30pm UK time. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;68%&lt;/strong&gt; were tech-related&lt;br /&gt;&lt;strong&gt;29%&lt;/strong&gt; were not tech-related&lt;br /&gt;&lt;strong&gt;3%&lt;/strong&gt; I couldn&#39;t be sure about&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;6%&lt;/strong&gt; I could not understand, tech or otherwise&lt;/p&gt;
&lt;p&gt;Of the &lt;strong&gt;68&lt;/strong&gt; tech related tweets,&lt;br /&gt;&lt;strong&gt;48 (71%)&lt;/strong&gt; were aiming to share something useful&lt;br /&gt;(retweets, links to resources, media)&lt;/p&gt;
&lt;p&gt;Of the &lt;strong&gt;29 &lt;/strong&gt;tweets not related to tech, subjects/themes were:&lt;br /&gt;&lt;strong&gt;4&lt;/strong&gt; Gender Inequality * &lt;br /&gt;&lt;strong&gt;2&lt;/strong&gt; Humorous (jokes/memes) &lt;br /&gt;&lt;strong&gt;2&lt;/strong&gt; Politics **&lt;br /&gt;&lt;strong&gt;2&lt;/strong&gt; Cats&lt;br /&gt;&lt;strong&gt;1&lt;/strong&gt; Dog&lt;br /&gt;&lt;strong&gt;1&lt;/strong&gt; Goats&lt;br /&gt;&lt;strong&gt;1&lt;/strong&gt; Game of Thrones&lt;br /&gt;&lt;strong&gt;1&lt;/strong&gt; Mental Health ***&lt;/p&gt;
&lt;p&gt;* It could be argued that these are tech related if the people tweeting are in the tech industry but it wasn&#39;t mentioned explicitly. Either way 4% or 1/25 tweets is very prominent.&lt;/p&gt;
&lt;p&gt;** This is despite my &quot;Trump&quot; and &quot;Brexit&quot; muted words.&lt;/p&gt;
&lt;p&gt;*** Big thumbs up!&lt;/p&gt;
&lt;p&gt;If anyone else would like to do the same exercise it would be interesting to compare and contrast results.&lt;/p&gt;
</description>
      <pubDate>Fri, 03 May 2019 18:00:36 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2019/what-techies-tweet/</guid>
    </item>
    <item>
      <title>When to Reach for a Framework (and When Not To)</title>
      <link>https://chrissmith.xyz/blog/2019/when-to-reach-for-a-framework-and-when-not-to/</link>
      <description>&lt;p&gt;First off, when I say &quot;framework&quot; in this post&#39;s title I just mean any big chunk of stuff that you load up and it does stuff for you. So, could be React, jQuery, Bootstrap, etc.&lt;/p&gt;
&lt;p&gt;Let&#39;s say that a &quot;framework&quot; is made up of 10 bits of functionality. If we use all 10 of them then we&#39;re getting great value from it. Conversely, if we&#39;re only using one or two we&#39;re probably loading up a lot of stuff that is never used - bloat.&lt;/p&gt;
&lt;h3&gt;DIY?&lt;/h3&gt;
&lt;p&gt;If you&#39;re only using one or two bits then you&#39;d probably be better off writing these parts yourself, if you can, or finding smaller libraries which do just the parts you need.&lt;/p&gt;
&lt;p&gt;If you go too far with trying to roll your own system you end up with a kind of framework but one that&#39;s made up of lots of disparate parts which may have other dependencies. It&#39;s a  Frankenstein&#39;s Monster of a framework. Hard to maintain and extend.&lt;/p&gt;
&lt;h3&gt;Tipping Point?&lt;/h3&gt;
&lt;p&gt;So, the real question is at what point do you move from assembling your own parts to adopting a full framework which organises these parts in a coherent and systemic way? Where&#39;s the tipping point?&lt;/p&gt;
&lt;p&gt;Going back to our example of a framework that offers 10 bits of functionality, how many would you want to be using to make adopting the framework worthwhile? I think it&#39;s important not to look at the now but at the future. Where is your project headed? Will it keep growing? What other functionality might you use further down the line? Does the framework given you other things for free that you can do now?&lt;/p&gt;
&lt;h3&gt;Framework Benefits&lt;/h3&gt;
&lt;p&gt;The other major benefit that a framework brings is the knowledge and familiarity. You can recruit someone who has worked with a framework before and they will be up to speed quite quickly compared with someone coming in and having to pick their way through a large custom system.&lt;/p&gt;
&lt;p&gt;If a framework offers 10 bits of functionality I&#39;d be inclined to adopt it as soon as you&#39;re using 3 of them. I feel the benefits of a framework outweigh the saving.&lt;/p&gt;
&lt;p&gt;You also have to consider the quality. Is a framework that has been worked on by top engineers and tested by thousands of developers going to be better than something you roll yourself? And will it integrate better with other third party tools?&lt;/p&gt;
&lt;h3&gt;Modules FTW&lt;/h3&gt;
&lt;p&gt;The real answer is for frameworks to become modular with a very small core and lots of optional modules. Not NPM which is going back to the &quot;Franken-framework&quot; but a properly connected set of features which can be included or dropped as needed. A bit of an old-school example now but &lt;a href=&quot;https://jqueryui.com/download/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot; aria-label=&quot;jQuery UI (opens in a new tab)&quot;&gt;jQuery UI&lt;/a&gt; does this very well - you can build a custom version of the library to suit your needs.&lt;/p&gt;
</description>
      <pubDate>Sat, 13 Apr 2019 08:58:13 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2019/when-to-reach-for-a-framework-and-when-not-to/</guid>
    </item>
    <item>
      <title>Hiding UI Elements</title>
      <link>https://chrissmith.xyz/blog/2019/hiding-ui-elements/</link>
      <description>&lt;p&gt;At the start of March 2019 I ran a poll on Twitter to see how devs hide UI elements. Here&#39;s the tweet and results.&lt;/p&gt;
&lt;p&gt;Admittedly, not a very scientific sample size but it was enough to confirm my suspicion that very few people use the &quot;hidden&quot; attribute. I should probably call it a property rather than an attribute as it&#39;s a Boolean and acts in a similar way to &quot;disabled&quot; or &quot;required&quot; which we often use on form elements. And, by contrast, the most common method seems to be to use the CSS &quot;display:none&quot;. Probably no great surprise to anyone.&lt;/p&gt;
&lt;p&gt;I think it&#39;s interesting to think about what we&#39;re really doing when we hide an element. Is the visibility of the element just for screen users or for all users? Do we still want the element available for non visual media? Or is the content going to be used by another part of the page in some way? Does it need to be in the DOM at all or are we just keeping it there because it&#39;s easier?&lt;/p&gt;
&lt;p&gt;If we use JavaScript, either native or a framework, we can insert and remove elements as needed based on logic. If it&#39;s playing no part in our document why not just leave it out altogether? This keeps the DOM light and performant and easier to work with. If you&#39;re working with something like automated testing you can check for an element&#39;s existence rather than trying to figure out if it&#39;s visible or not.&lt;/p&gt;
&lt;p&gt;If we use CSS to hide an element and respect the separation of concerns principle then are we saying that hiding this element is a presentational choice rather than a semantic one? Maybe we are hiding it, maybe temporarily, rather than denying its existence?&lt;/p&gt;
&lt;p&gt;In the case where we want an element to be hidden in one medium and shown in another, CSS feels like the right choice. Whilst &quot;display:none&quot; and &quot;visibility:hidden&quot; are valid, other techniques like &quot;height:0&quot;, &quot;opacity:0&quot; or &quot;left:9999px&quot; feel very unclear in their intentions and too focused on the visual user.&lt;/p&gt;
&lt;p&gt;The HTML &quot;hidden&quot; property is a more semantic choice. It is stating that this element is not to be considered when reading the document, whether that be on screen or via assistive technologies. It is about more than visibility and is probably badly named. Maybe &quot;ignore&quot; would have been more fitting? It is more about the state of the element and closer in meaning to the input[type=hidden] that we used to see in the days before Ajax.&lt;/p&gt;
&lt;p&gt;If you take away the JavaScript and CSS - maybe some network issues, maybe the HTML gets copied elsewhere - the element stays hidden. The point is that it&#39;s meant to be hidden, it&#39;s not styling.&lt;/p&gt;
&lt;p&gt;The &quot;hidden&quot; property is also easy to work with and change in JavaScript. In fact, it&#39;s easier than using a CSS class as you don&#39;t have to write any CSS and you know it will work regardless.&lt;/p&gt;
&lt;pre class=&quot;wp-block-code&quot;&gt;&lt;code&gt;&amp;lt;p class=&quot;disclaimer&quot; hidden&gt;This is a disclaimer&amp;lt;/p&gt;

&amp;lt;script&gt;
  const disclaimer = document.querySelector(&#39;.disclaimer&#39;);
  function showDisclaimer() {
    // with a CSS class
    disclaimer.classList.add(&#39;show&#39;);
    // with the hidden property
    disclaimer.hidden = false;
  }
&amp;lt;/script&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;!-- /wp:code --&gt;
&lt;p&gt;Think about why your content is hidden and how it may be reused and choose the most appropriate method of hiding it (or removing it).&lt;/p&gt;
</description>
      <pubDate>Fri, 29 Mar 2019 18:00:17 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2019/hiding-ui-elements/</guid>
    </item>
    <item>
      <title>What I Learned in 2018</title>
      <link>https://chrissmith.xyz/blog/2018/what-i-learned-in-2018/</link>
      <description>&lt;p&gt;I write a post like this every year and it feels like it gets harder each time. There was a time when I could rattle through a list of new tech, tools or libraries that I&#39;d been using. It feels like I&#39;m much more focused on soft skills these days or firming up what I already know.&lt;/p&gt;
&lt;h3&gt;Running Workshops&lt;/h3&gt;
&lt;p&gt;This year I&#39;ve started running workshops to share knowledge with other developers. I&#39;ve run short half hour workshops on Semantic HTML, Sass, Web Workers, Service Workers and Flexbox. I&#39;m not a natural teacher or presenter but it&#39;s been great to give other developers dedicated time to learn something new and by putting together a workshop it&#39;s made me firm up my knowledge of each subject. I&#39;d definitely recommend it as a worthwhile activity to anyone.&lt;/p&gt;
&lt;h3&gt;Design System&lt;/h3&gt;
&lt;p&gt;After a period of research and seeing what other companies are doing, I&#39;ve started a design system, documenting UI patterns and styling advice. It feels good to have things documented in one place rather than in my head or having to go back and find the most recent or best usage. I&#39;ve built a base system which loads HTML pages and then created a HTML page for each design element. This gives the flexibility to be able to move the content into another environment in the future without having to start from scratch. It makes heavy use of CodePen embeds to demo the result and share the HTML and CSS.&lt;/p&gt;
&lt;h3&gt;Design Audit&lt;/h3&gt;
&lt;p&gt;I&#39;ve learned about design audits and ways of going about bringing designs of separate sites or software together. This is the method we&#39;re planning to adopt:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;Select a design element, e.g. buttons.&lt;/li&gt;&lt;li&gt;Go through every page of your site or app and screenshot every different variation which you find.&lt;/li&gt;&lt;li&gt;Put all of the screenshots into an audit document.&lt;/li&gt;&lt;li&gt;Present these differences so that others are aware of the scale of the inconsistency.&lt;/li&gt;&lt;li&gt;Agree on one correct design with which to move forwards.&lt;/li&gt;&lt;li&gt;Change each variation to the new correct design. As you do so, remove that variation from your audit document.&lt;/li&gt;&lt;li&gt;Over time the audit document gets smaller and smaller until it is no longer needed.&lt;/li&gt;&lt;/ol&gt;
&lt;h3&gt;Web Workers&lt;/h3&gt;
&lt;p&gt;Learning about Web Workers and how you can send some operations off to be carried out in the background was very interesting. I&#39;m yet to find a real life use case for them but it certainly opens up a lot of possibilities having multiple threads running instead of just one.&lt;/p&gt;
&lt;h3&gt;Service Workers&lt;/h3&gt;
&lt;p&gt;This is another area which seems to have a huge potential, not only for performance by loading resources from the cache but also being able to provide offline content and create a Progressive Web App, a web based app which can run offline just like a native app. I&#39;m hoping to create my own app some time in 2019.&lt;/p&gt;
&lt;h3&gt;Custom Elements&lt;/h3&gt;
&lt;p&gt;Towards the end of the year a colleague introduced me to Custom Elements. I was vaguely aware of them before but without the browser support hadn&#39;t taken too much notice. Now they&#39;re usable. Being able to make your own elements that work independently of any framework is very powerful. It means that we&#39;re not longer limited to using a single framework or framework version in an app or across teams.&lt;/p&gt;
&lt;h3&gt;ES6&lt;/h3&gt;
&lt;p&gt;The final thing that I&#39;ve been working on is trying to improve my use of ES6, gradually trying to break old habits and write in the newer, easier style. The biggest breakthrough I&#39;ve found is the backtick syntax, being able to write HTML and use ${variable} within it for binding. It&#39;s a lot easier than lots of document.createElement() and then setting innerHTML or textContent.&lt;/p&gt;
&lt;h3&gt;2019?&lt;/h3&gt;
&lt;p&gt;Basically I&#39;m aiming to put all of this new learning from 2018 into practice and get some real working examples.&lt;/p&gt;
</description>
      <pubDate>Thu, 27 Dec 2018 19:00:57 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2018/what-i-learned-in-2018/</guid>
    </item>
    <item>
      <title>The DOM Diet and Year Pickers</title>
      <link>https://chrissmith.xyz/blog/2018/the-dom-diet-and-year-pickers/</link>
      <description>&lt;p&gt;I think we all know that having a smaller DOM is good for performance but I was never sure what&#39;s considered big or small, or at what points performance is affected. Knowing a little more can change how you approach things.&lt;/p&gt;
&lt;p&gt;I was recently doing a performance analysis on some pages and the tool I chose to use was the Chrome Performance Audit. If you open Dev Tools (F12) and go to the Audits tab you&#39;ll see a range of available audits which includes Performance. This uses a tool called Lighthouse and gives estimates for various performance metrics as well as Opportunities and Diagnostics.&lt;/p&gt;
&lt;p&gt;One of the diagnostics which came up for me was &amp;quot;&lt;a href=&quot;https://developers.google.com/web/tools/lighthouse/audits/dom-size&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Uses an excessive DOM size&lt;/a&gt;&amp;quot; and the detail gives us this:&lt;/p&gt;
&lt;blockquote&gt;Browser engineers recommend pages contain fewer than ~1,500 DOM nodes. The sweet spot is a tree depth &amp;lt; 32 elements and fewer than 60 children/parent element. A large DOM can increase memory usage, cause longer &lt;a href=&quot;https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;style calculations&lt;/a&gt;, and produce costly &lt;a href=&quot;https://developers.google.com/speed/articles/reflow&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;layout reflows&lt;/a&gt;.&lt;/blockquote&gt;
The item that triggered this diagnostic for me was a year picker, a select element with 150 options. Whilst I don&#39;t think it&#39;s really causing any major performance issues it did strike me that 1 parent element and 150 children does seem excessive for just picking out one number from a consecutive range so I started looking at alternative ways we could do this. I wanted to put my year picker on a  &quot;DOM Diet&quot;. I created this pen:
&lt;p&gt;[codepen_embed height=&amp;quot;520&amp;quot; theme_id=&amp;quot;dark&amp;quot; slug_hash=&amp;quot;MzJrjL&amp;quot; default_tab=&amp;quot;result&amp;quot; user=&amp;quot;chris22smith&amp;quot; editable=&amp;quot;true&amp;quot; data-editable=&amp;quot;true&amp;quot;]See the Pen &lt;a href=&quot;https://codepen.io/chris22smith/pen/MzJrjL/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Year Pickers&lt;/a&gt; by Chris Smith (&lt;a href=&quot;https://codepen.io/chris22smith&quot;&gt;@chris22smith&lt;/a&gt;) on &lt;a href=&quot;https://codepen.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;CodePen&lt;/a&gt;.[/codepen_embed]&lt;/p&gt;
&lt;p&gt;Here&#39;s a quick comparison of 4 possible ways of selecting a year from a consecutive range. It&#39;s important to not only look at possible DOM performance but also the user experience side - ease of understanding and ease of use. No point making it faster if it&#39;s confusing or hard work.&lt;/p&gt;
&lt;h3&gt;Select/Dropdown&lt;/h3&gt;
This is the standard method. It can have a default value or a blank value as the first option. It&#39;s very familiar, ease to understand and use. It&#39;s probably better to start with a blank value so that we know a user has actually made a selection rather than just left the default. It supports arrow keys and mousewheel. It&#39;s easy to validate using just the required property as the available options are set. It can look untidy in some browsers when long option lists run off the bottom of the screen and it does use a lot of DOM nodes.
&lt;h3&gt;Range Input&lt;/h3&gt;
The input[type=range] doesn&#39;t show a value by default so you have to do a bit of work to show an output value, and a bit more work to do this elegantly. Through testing I found the output value had to go above the slider rather than below so it was not obscured by a finger using the control. I think this is fairly easy to understand but users may not be aware that they can use their arrow keys to get greater precision - either up/down or left/right. It can be hard to control and get the exact figure you want dragging the handle especially using a finger. It can also be wired up to support the wheel event and respond to scrolling up or down on the mousewheel. There&#39;s no way to have a blank value so it has to have a default set. There&#39;s no real validation to be done as it has to use a value in the range. It&#39;s very kind to the DOM too with only 3 nodes.
&lt;h3&gt;Number Input&lt;/h3&gt;
This method is very simple. You just let the user type in the date they want. It can be left blank or have a default value. It can be controlled using arrow keys or the mousewheel though I&#39;m not sure how many users know this. By setting the min, max and step attributes it can limit the range entered when not typing. If the value is typed (or pasted) it will require validation. This uses a single DOM node.
&lt;h3&gt;Multiple Number Inputs&lt;/h3&gt;
This final method is just a bit of a &quot;left field&quot; design. The advantage of it is that it&#39;s very easy to update using the tab key and arrow keys. By having the digits separated the range for each is only ever 10 so in theory it should mean less to change. If left blank it could be set to automatically shift the focus to the next input when a value is added. This makes it as fast to type the 4 digits as a single number input. The min, max and step attributes can limit the range for each digit. It&#39;s light on the DOM too with only 5 nodes. The disadvantage with this method is the validation - it&#39;s going to be a bit more involved, parsing the 4 digits as a single value to be checked and then highlighting the invalid digit(s) could be difficult. On a mobile device with a number pad it also means the pad flashing in and out quickly, which is not a great experience so it&#39;s only really suitable for desktop use.
&lt;p&gt;I&#39;m not sure I&#39;d necessarily go running from the standard dropdown but some of the other methods are certainly possibilities and help keep the DOM smaller.&lt;/p&gt;
</description>
      <pubDate>Thu, 15 Nov 2018 16:43:21 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2018/the-dom-diet-and-year-pickers/</guid>
    </item>
    <item>
      <title>Why Are We Making Web Development So Hard?</title>
      <link>https://chrissmith.xyz/blog/2018/why-are-we-making-web-development-so-hard/</link>
      <description>&lt;p&gt;I don&#39;t think I&#39;m the first person to think this by any stretch. There are lots of infographics around showing the difference between web tooling now and 10 years ago and it&#39;s clearly ballooned at an extraordinary rate.&lt;/p&gt;
&lt;p&gt;In the last year or so I&#39;ve started working with Angular (as opposed to Angular.js a.k.a. Angular 1) and have also dabbled in Vue and React. All of these frameworks seem to share the same basic ideas - build everything as a component and push and pull them from the &lt;abbr title=&quot;Document Object Model&quot;&gt;DOM&lt;/abbr&gt; as needed. Each component is made up of a HTML template, embedded CSS styles and a JavaScript controller.&lt;/p&gt;
&lt;p&gt;This feels like an efficient way of working, very &lt;abbr title=&quot;Don&#39;t Repeat Yourself&quot;&gt;DRY&lt;/abbr&gt;. But is it? You create a component, let&#39;s say a time picker. One it&#39;s developed you can put it into multiple views or uses relatively quickly. However, if you later modify it to work slightly differently, using adding complexity, you have to test it in each use case and make sure it still works with no detrimental effects.&lt;/p&gt;
&lt;p&gt;All &lt;abbr title=&quot;User Interface&quot;&gt;UI&lt;/abbr&gt;s are basically built up of HTML, CSS and JavaScript. Traditionally HTML is for content, CSS for styling and JavaScript for reacting to user behaviour. With components we&#39;re adding a whole load of JavaScript just to make the basic elements appear before we even get into any behavioural usage. This adds to page weight (size of files being transferred to the browser) and render times. There&#39;s the library itself, often split into many smaller modules, plus a controller for the UI to assemble it and then the components. It could just be one HTML file, one CSS file and one JavaScript file.&lt;/p&gt;
&lt;p&gt;Increasingly, what the developer writes in their editor is becoming further and further from what actually appears in the &lt;abbr title=&quot;Document Object Model&quot;&gt;DOM&lt;/abbr&gt;. The frameworks insert a whole host of IDs and classes to elements, bloating the HTML and making it harder to read. Styles are inserted as inline &amp;lt;style&amp;gt; blocks rather than being cached in an external stylesheet. Opening the browser&#39;s Dev Tools to track down and fix a problem is becoming harder, not easier.&lt;/p&gt;
&lt;p&gt;Also, the more tools you use, the more you&#39;ve got to maintain, keep up to date, upgrade and replace. It&#39;s creating work just to keep up and inviting technical debt.&lt;/p&gt;
&lt;p&gt;I think that what we&#39;re gaining in terms of being able to develop new UI more quickly is all rooted in developer efficiency and production cost saving. It&#39;s not thinking about the user. We&#39;re making things slower for users. The mobile experience on most sites is still awful and the overhead of these frameworks is partly to blame.&lt;/p&gt;
&lt;p&gt;The latest frameworks also rely on good browsers with all the JavaScript features. They do not use progressive enhancement but just grind to a halt on an older browser. This goes against the universal nature of the web - it should be easy to read and easy to write. The bells and whistles on the top is just that and should be optional, not prevent the basics from working.&lt;/p&gt;
&lt;p&gt;I think we need to get back to making things simple. Write HTML, CSS and as little JavaScript as we can get away with. Go static wherever possible. Make it fast and simple for users. User experience should trump developer experience.&lt;/p&gt;
</description>
      <pubDate>Wed, 24 Oct 2018 17:47:09 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2018/why-are-we-making-web-development-so-hard/</guid>
    </item>
    <item>
      <title>Learning Experiences as a Freelancer</title>
      <link>https://chrissmith.xyz/blog/2018/learning-experiences-as-a-freelancer/</link>
      <description>&lt;p&gt;I thought it might be useful to share some of my not-so-great experiences as a freelance web designer so that others can learn from my mistakes.&lt;/p&gt;
&lt;h3&gt;All Work and No Pay&lt;/h3&gt;
What&#39;s really frustrating is that I made the same mistake several times. That costly mistake was doing work and not getting paid for it. I&#39;d get an enquiry for building a site by phone or email. I&#39;d get straight back with some ideas and a quote and more often than not my quote would be accepted. I&#39;d even have written confirmation that yes, they wanted to pay me for a website. On this basis I&#39;d do the work and then when it came to sharing my design they&#39;d say that they didn&#39;t want to go ahead any more or that they&#39;d found another designer.
&lt;p&gt;It&#39;s hard as a designer. You can get excited by a project. As soon as you finish speaking to the customer the ideas start flooding into your head and you want to capture that excitement and creativity there and then. Unfortunately, in my experience it often doesn&#39;t actually materialise. They&#39;re just not as serious about the project as you think they are.&lt;/p&gt;
&lt;p&gt;My advice would be to assume that it&#39;s just talk until you see some commitment, and by commitment I mean money. Ask for a deposit. It doesn&#39;t have to be much, even £10 or $10 will do, but it&#39;s just enough to prove that they&#39;re serious. Don&#39;t lift a finger until you&#39;ve got a serious commitment. Trust me -you can&#39;t afford to work for nothing.&lt;/p&gt;
&lt;h3&gt;The Price is Right&lt;/h3&gt;
The other mistake I made was in my pricing. As I was fairly new to web design I thought I&#39;d hit the low end of the market where I could compete on price and get lots of small cheap sites in my portfolio. It worked well for some customers but it&#39;s surprising how many people expect you to travel to see them at your expense when you&#39;re charging less than £100 for a website. The only way you can operate at the cheap end is by having very low outgoing costs.
&lt;p&gt;Later, when I stopped being a full-time freelancer and moved into a permanent job I kept the web design going as a side line. At this point I could afford to be more picky about which projects I took on, and, without needing to be so competitive I raised my prices. In fact, I doubled my prices. Here&#39;s the thing. I was expecting my number of enquiries to drop off. It didn&#39;t. It pretty much doubled. I think that going too cheap was actually suggesting low quality or making people suspicious. Charging more can suggest higher quality and strangely provide some reassurance.&lt;/p&gt;
&lt;p&gt;My advice would be to find the price that you think your service is worth and then double it. Serious customers want to buy quality services and with something like a website they&#39;re looking for a long term relationship, not a quick handover.&lt;/p&gt;
&lt;h3&gt;Losing Focus&lt;/h3&gt;
The third mistake I made was spending my time on the wrong things. I spent a lot of time trying to market myself rather than focusing on client work. I put a lot of hours into studying Google Analytics, SEO and building other sites to promote my main business. It would have been far more cost effective to just pay for advertising rather than commit this time. Trying to market myself by spending time and not money was a false economy. Focus on what you&#39;re good at and pay others to do what they&#39;re good at.
&lt;p&gt;Hope that helps someone.&lt;/p&gt;
</description>
      <pubDate>Sat, 06 Oct 2018 18:01:30 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2018/learning-experiences-as-a-freelancer/</guid>
    </item>
    <item>
      <title>Super Fast Tree View in JavaScript</title>
      <link>https://chrissmith.xyz/blog/2018/super-fast-tree-view-in-javascript/</link>
      <description>&lt;p&gt;I thought I&#39;d share a way of writing your JavaScript that will make a tree view hierarchy render and respond very quickly.&lt;/p&gt;
&lt;p&gt;Firstly, the demo. I&#39;ve got 100,000 items, quite a hefty data set, which is randomly generated in a function. You can change the number of items easily in the JS area. Click on the + or - icons to expand or collapse nodes.&lt;/p&gt;
&lt;p&gt;[codepen_embed height=&amp;quot;520&amp;quot; theme_id=&amp;quot;dark&amp;quot; slug_hash=&amp;quot;WawYKX&amp;quot; default_tab=&amp;quot;result&amp;quot; user=&amp;quot;chris22smith&amp;quot; editable=&amp;quot;true&amp;quot; data-editable=&amp;quot;true&amp;quot;]See the Pen &lt;a href=&quot;https://codepen.io/chris22smith/pen/WawYKX/&quot;&gt;Super Fast JavaScript Data Tree&lt;/a&gt; by Chris Smith (&lt;a href=&quot;https://codepen.io/chris22smith&quot;&gt;@chris22smith&lt;/a&gt;) on &lt;a href=&quot;https://codepen.io/&quot;&gt;CodePen&lt;/a&gt;.[/codepen_embed]&lt;/p&gt;
&lt;p&gt;It&#39;s still quick, like instant, with 100,000 items. It can start to slow a little at a million but I&#39;d say it&#39;s still acceptable given that kind of data.&lt;/p&gt;
&lt;h3&gt;One Long List&lt;/h3&gt;
The trick is in how the data is structured. It&#39;s one big array, not hierarchical data with objects inside other objects. The reason for this is pretty simple, it&#39;s all about iterations or looping. If you have a single array you can run through the whole list of items once. If it&#39;s nested you have to get into loops inside other loops and it gets more complicated and takes longer. In fact, you&#39;d be lucky for it to work at all without getting stack overflow errors.
&lt;h3&gt;JavaScript Magic&lt;/h3&gt;
With a single array you can use the built in JavaScript Array methods, which are very fast - &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;map()&lt;/a&gt;, &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;filter()&lt;/a&gt; and &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;some()&lt;/a&gt;. I&#39;d definitely recommend reading up on these. All three work in IE9+ so hopefully you shouldn&#39;t have to worry too much about browser support.
&lt;p&gt;I use &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;map()&lt;/a&gt; to convert each data item into a HTML list item which I can insert into the DOM. I use &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;filter()&lt;/a&gt; to quickly find the children items of any item by returning a subset, and I use &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;some()&lt;/a&gt; to see if an item has children. The beauty of &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;some()&lt;/a&gt; is that once its found it child it stops iterating, saving time.&lt;/p&gt;
&lt;h3&gt;Easy on the DOM&lt;/h3&gt;
The other part of this is keeping DOM manipulation to a minimum. Playing around with data in memory trivial for a browser but making changes to the DOM and rendering things on screen takes time. So, only the nodes that are needed right now exist in the DOM - there are not hidden items waiting on the sidelines. So, a new &amp;lt;ul&amp;gt; is added when you expand a node and the &amp;lt;ul&amp;gt; is removed when you collapse. A + icon is shown if the item has children of its own but we don&#39;t know anything about how many it has or what they contain until it&#39;s expanded.
&lt;h3&gt;More...&lt;/h3&gt;
If you found this useful it might be worth looking at my older post &lt;a href=&quot;https://chrissmith.xyz/blog/lightning-fast-filtering-in-javascript/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Lightning Fast Filtering in JavaScript&lt;/a&gt;, which uses a lot of the same principles.
</description>
      <pubDate>Fri, 05 Oct 2018 16:25:04 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2018/super-fast-tree-view-in-javascript/</guid>
    </item>
    <item>
      <title>Stop Linking to Nowhere</title>
      <link>https://chrissmith.xyz/blog/2018/stop-linking-to-nowhere/</link>
      <description>&lt;p&gt;Do you find yourself writing this kind of thing in your HTML?
&lt;code&gt;&amp;lt;a href=&amp;quot;#&amp;quot; onclick=&amp;quot;doSomething()&amp;quot;&amp;gt;Some action&amp;lt;/a&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Does that &lt;code&gt;href=&amp;quot;#&amp;quot;&lt;/code&gt; make you feel slightly uncomfortable? Like it&#39;s not really doing anything, a bit of a hack? You&#39;d be dead right to think that.&lt;/p&gt;
&lt;p&gt;Links are used like this all the time and there&#39;s really no need. The intended purpose of links is to point to another location and provide navigation. That&#39;s why the href is there. It&#39;s pointing to another place but it&#39;s often left pointing nowhere.&lt;/p&gt;
&lt;p&gt;It&#39;s probably worth pointing out that using &lt;code&gt;href=&amp;quot;#&amp;quot;&lt;/code&gt; doesn&#39;t actually do nothing. It adds a # onto your current location, changing the URL, so when you then click the back button it appears to do nothing but is actually going back to the last location, the URL without the #. If you do use &lt;code&gt;href=&amp;quot;#&amp;quot;&lt;/code&gt; and an onclick event be sure to use &lt;code&gt;event.preventDefault()&lt;/code&gt; with it to prevent this location change.&lt;/p&gt;
&lt;p&gt;Links get used in this way mainly because we want the styling and the interactivity. Hovering a link gives visual cues - underline changes, cursor changes so it&#39;s easy for a user to see it&#39;s something they can interact with.&lt;/p&gt;
&lt;p&gt;So, what&#39;s the alternative? If you&#39;re just performing an action, use a button. It has the visual cues. It doesn&#39;t have any hacky &lt;code&gt;href=&amp;quot;#&amp;quot;&lt;/code&gt; nonsense. It can be styled however you wish if the default styling is too full-on. It can even be styled to look exactly like a link, though personally I think there&#39;s value in differentiating between navigation and actions.&lt;/p&gt;
&lt;p&gt;And there&#39;s more... You get some more benefits for free with a button.&lt;/p&gt;
&lt;p&gt;You have a disabled property. You can easily make your action unavailable. Not so easy with a link.&lt;/p&gt;
&lt;p&gt;It&#39;s more touch friendly. This depends on styling but out-of-the-box it&#39;s a larger touch target.&lt;/p&gt;
&lt;p&gt;It has an autofocus property so it can be in focus on page load without needing any JavaScript. Ready to go at the tap of the Enter key.&lt;/p&gt;
&lt;p&gt;If you use links for navigation and buttons for actions you get every tool doing what it&#39;s best at. You could cut your food with the side of your fork and raise it to your mouth on the side of your knife but why would you? This isn&#39;t really so different.&lt;/p&gt;
</description>
      <pubDate>Wed, 01 Aug 2018 17:26:36 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2018/stop-linking-to-nowhere/</guid>
    </item>
    <item>
      <title>Google Analytics - Why You Should Replace IDs in URLs</title>
      <link>https://chrissmith.xyz/blog/2018/google-analytics-why-you-should-replace-ids-in-urls/</link>
      <description>&lt;p&gt;Google Analytics is brilliant at tracking things like Page Views for a website. It logs the URL and then keeps a count of how may times that URL is requested. Great, right? Not always.&lt;/p&gt;
&lt;p&gt;There&#39;s a problem. Dynamic sites that use IDs in their URLs generate a lot of different URLs. A typical example might be a site being made up of list and details screens, so the URL for a list screen might end in &lt;code&gt;/List/&lt;/code&gt;. For a details page there&#39;s probably one template with the data changing dynamically and the ID for that item is probably in the URL, something like &lt;code&gt;/Details/123&lt;/code&gt; or &lt;code&gt;/Details?id=123&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This means that Google Analytics sees every visit to a different item&#39;s details as a different screen. This is ideal for some data analysis, like seeing which item is viewed most but not so great when you want to look at something like the performance of that template. Having hundreds of different URLs makes it impossible to analyse the template as a single screen.&lt;/p&gt;
&lt;p&gt;Good news. It&#39;s quite easy to set up another view to show the aggregated data using filters.&lt;/p&gt;
&lt;ol&gt;
 	&lt;li&gt;Go to the Admin area and create a new view.&lt;/li&gt;
 	&lt;li&gt;Find Filters and add a new filter.&lt;/li&gt;
 	&lt;li&gt;Add a Filter Name.&lt;/li&gt;
 	&lt;li&gt;Select a Filter Type of Custom.&lt;/li&gt;
 	&lt;li&gt;Use the Search and Replace option.&lt;/li&gt;
 	&lt;li&gt;Select a Filter Field of Request URI.&lt;/li&gt;
 	&lt;li&gt;The Search String needs to match the ID. You can use regex to match any patterns so if you know your ID is 3-5 digits long you can use &lt;code&gt;[0-9]{3,5}&lt;/code&gt;. If it varies you could use a wildcard, like &lt;code&gt;id=*&lt;/code&gt;.&lt;/li&gt;
 	&lt;li&gt;Add a Replace String. I use something to represent what&#39;s being replaced, like ID. This gives me a URL like &lt;code&gt;/Details/ID&lt;/code&gt; or &lt;code&gt;/Details?id=ID&lt;/code&gt;. If you&#39;ve used a wildcard in the Search String with part of the URL you can replace this too, like &lt;code&gt;id=ID&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
Here&#39;s an example of replacing a GUID in the URL:
&lt;p&gt;&lt;img class=&quot;aligncenter wp-image-806&quot; title=&quot;Google Analytics Filtering screenshot&quot; src=&quot;https://chrissmith.xyz/img/2018/08/replace-guid-filter.png&quot; alt=&quot;Google Analytics Filtering screenshot&quot; width=&quot;320&quot; height=&quot;456&quot; /&gt;The full regex needed is:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;code&gt;[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}&lt;/code&gt;&lt;/p&gt;
An added bonus. When you look at your reports in Google Analytics you&#39;ll no longer see URLs like &lt;code&gt;/Details/aace7226-0576-4a0f-9b39-bb549a53ee11&lt;/code&gt; but just &lt;code&gt;/Details/GUID&lt;/code&gt;. Much easier to understand, especially if your URL contains several IDs or GUIDs.
&lt;p&gt;Hope this helps you analyse your screens, templates or UIs rather than just the data requested.&lt;/p&gt;
</description>
      <pubDate>Wed, 01 Aug 2018 16:53:19 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2018/google-analytics-why-you-should-replace-ids-in-urls/</guid>
    </item>
    <item>
      <title>Experiment: Font Size vs Colour Contrast</title>
      <link>https://chrissmith.xyz/blog/2018/experiment-font-size-vs-colour-contrast/</link>
      <description>&lt;p&gt;One of the things I&#39;ve learned early on in web accessibility is the importance of colour contrast to make things easy to read on screen. High contrast is good but the size of text is also a factor. If it&#39;s larger it&#39;s easier to read even if the contrast drops.&lt;/p&gt;
&lt;p&gt;At the same time, having very large text with high contrast is quite &amp;quot;full on&amp;quot;. It can feel a bit like you&#39;re being shouted at. &lt;em&gt;Oppressive&lt;/em&gt; is the word I&#39;d use.&lt;/p&gt;
&lt;p&gt;This got me thinking. I wonder if we can scale colour contrast with font size so that it always feels good. It&#39;s really an extension of responsive design.&lt;/p&gt;
&lt;p&gt;So, I tried it in CodePen.&lt;/p&gt;
&lt;p&gt;[codepen_embed height=&amp;quot;600&amp;quot; theme_id=&amp;quot;1248&amp;quot; slug_hash=&amp;quot;ajvVPL&amp;quot; default_tab=&amp;quot;result&amp;quot; user=&amp;quot;chris22smith&amp;quot; editable=&amp;quot;true&amp;quot; data-editable=&amp;quot;true&amp;quot;]See the Pen &lt;a href=&quot;https://codepen.io/chris22smith/pen/ajvVPL/&quot;&gt;Font Size vs Color Contrast&lt;/a&gt; by Chris Smith (&lt;a href=&quot;https://codepen.io/chris22smith&quot;&gt;@chris22smith&lt;/a&gt;) on &lt;a href=&quot;https://codepen.io/&quot;&gt;CodePen&lt;/a&gt;.[/codepen_embed]&lt;/p&gt;
&lt;p&gt;I&#39;ve just done some very crude maths to make the RGB colour proportional to the font-size. As the font gets larger so do the RGB values, and vice versa.&lt;/p&gt;
&lt;p&gt;I&#39;m sure there&#39;s probably some beautiful golden formula for getting the optimum contrast at every size but I wouldn&#39;t really know how to go about finding these optimum settings. This experiment seems to prove that the general idea is sound though.&lt;/p&gt;
&lt;p&gt;Please feel free to play around with it, take it further and let me know how you get on.&lt;/p&gt;
</description>
      <pubDate>Fri, 13 Jul 2018 19:13:37 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2018/experiment-font-size-vs-colour-contrast/</guid>
    </item>
    <item>
      <title>Making Icons Accessible</title>
      <link>https://chrissmith.xyz/blog/2018/making-icons-accessible/</link>
      <description>&lt;p&gt;I&#39;ve been using the excellent Font Awesome for a few years and it&#39;s become part of almost every new design that I do. For a long time I&#39;ve just slapped my icon down on the page, styled it and added a click event where needed. Job done.&lt;/p&gt;
&lt;p&gt;Having spent some time looking a bit more deeply into accessibility, I can now see that this is not a great approach. There&#39;s more to consider. If you can&#39;t see it what is it actually doing?&lt;/p&gt;
&lt;p&gt;Here&#39;s how I approach using icons now. It may not be the perfect solution but it&#39;s certainly a lot closer than most use cases I see. The way I use HTML depends on the use case.&lt;/p&gt;
&lt;p&gt;If the icon is purely decorative - there in addition to text, e.g. a floppy disk icon next to the word &amp;quot;Save&amp;quot; on a button, then I think we can reasonably just forget about it and hide it for non screen users. A simple aria-hidden=&amp;quot;true&amp;quot; attribute should do.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;button&amp;gt;&amp;lt;i class=&amp;quot;fa fa-save&amp;quot; aria-hidden=&amp;quot;true&amp;quot;&amp;gt;&amp;lt;/i&amp;gt; Save&amp;lt;/button&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;If it is there as an indicator, in place of a label, like where a hotel might have icons for TV, bath, etc. then we can use an &amp;lt;span&amp;gt; to wrap it. Inside the span we add our icon and another span with a text alternative. We show the icon and hide the inner span for screens, show the text only for other media.&lt;/p&gt;
&lt;p&gt;Finally, if the icon is interactive and acts like a link or button, let&#39;s make it a link or button. Like the previous example, use the &amp;lt;button&amp;gt; or &amp;lt;a&amp;gt; tag to wrap the icon and a span text alternative and show/hide for the appropriate media. This has the added bonus of making it possible to tab to the icon and so use just the keyboard to navigate the page. It also handles the icon&#39;s active state and visited in the case of a link.&lt;/p&gt;
&lt;p&gt;Alternatively, if you didn&#39;t want to add a span with text inside your button or link, you could use the aria-label attribute to provide a text alternative.&lt;/p&gt;
&lt;p&gt;One little tip. If you use an icon inside a link or button, do not leave whitespace between the outer wrapper element and the inner icon as you may get unwanted effects in the styling, such as underlined spaces either side of your icon. Keep it tight.&lt;/p&gt;
</description>
      <pubDate>Wed, 16 May 2018 17:42:34 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2018/making-icons-accessible/</guid>
    </item>
    <item>
      <title>A New Found Appreciation for Images on the Web</title>
      <link>https://chrissmith.xyz/blog/2018/a-new-found-appreciation-for-images-on-the-web/</link>
      <description>&lt;p&gt;I&#39;ve been putting images in web pages for years. Nearly 2 decades now. For most of that time it has been quite easy. Add your source and the dimensions and BOOM, there you go. There was always some work around optimising images outside of your page but once in there, easy.&lt;/p&gt;
&lt;p&gt;Then, with higher pixel densities it started getting a bit harder and we had to work it out with media queries and srcset. Now SVG is widely supported, all this fussing around with different versions for different resolutions has gone away, at least for simple graphics.&lt;/p&gt;
&lt;p&gt;I&#39;ve recently been doing some design work on an Android app and it&#39;s a very different way of doing things with images. For example, I&#39;ve created a splash screen for while the app is loading. It&#39;s a full page, wide logo in the centre, coloured background.&lt;/p&gt;
&lt;p&gt;On the web, I&#39;d just set the background colour and then centre the SVG logo, probably with flexbox, and use a flex-basis of 80% or some margin to give it a flexible width.&lt;/p&gt;
&lt;p&gt;On Android, I&#39;ve had to provide the splash screen image as a series of PNG files. 5 different resolutions, varying from 480x320 up to 1920x1280, and then in both orientations, 10 files in all. The clever part is that at the point of installing the app the Android device will only get the files appropriate for its size and pixel density but it means a lot of messing around with assets.&lt;/p&gt;
&lt;p&gt;It&#39;s been a similar story for icons too. Multiple resolutions. You want a different colour? That&#39;s a separate PNG.&lt;/p&gt;
&lt;p&gt;I&#39;m making it sound worse than it actually is. Luckily there are great tools that let you import a single image and export all the variations you could need.&lt;/p&gt;
&lt;p&gt;But it does make you think about the differences between platforms. To me, the web browser, with it&#39;s ability to resize on the fly, use SVG, recolour, apply filters, transform and animate in CSS makes Android image support feel very primitive.&lt;/p&gt;
</description>
      <pubDate>Wed, 09 May 2018 17:17:46 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2018/a-new-found-appreciation-for-images-on-the-web/</guid>
    </item>
    <item>
      <title>How to Be a Good Designer</title>
      <link>https://chrissmith.xyz/blog/2018/how-to-be-a-good-designer/</link>
      <description>&lt;p&gt;I&#39;ve been designing web sites and user interfaces for quite a long time now and thought I&#39;d try to pass on what I think it takes to be a good designer. This isn&#39;t about design techniques or theory, just how to interact with other people.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rule 1. Don&#39;t be a dick.&lt;/strong&gt;
That&#39;s really it. Don&#39;t let your ego take over. You will inevitably have to present your work to others. Don&#39;t presume that because you&#39;re the designer that your opinion is worth more than anyone else&#39;s. It&#39;s a collaborative process and if you start feeling that you know best it will stop you listening to others. This leads neatly into...&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rule 2. Listen to others.&lt;/strong&gt;
This isn&#39;t because you have to or to be polite. If you actually listen and understand people&#39;s views, opinions and concerns you can learn how to adapt your designs to meet their needs or explain how there might be a different solution to the problem.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rule 3. Explain your thinking.&lt;/strong&gt;
Don&#39;t just present a design and let others judge it. Explain clearly all of the design decisions you have made. If you can justify these and articulate them clearly people will understand, you&#39;ll have more of a conversation and, in turn, their feedback will be more constructive. It will also give them more faith in you - you don&#39;t do things on a whim but your decisions are well thought out.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rule 4. You don&#39;t have to win.&lt;/strong&gt;
It&#39;s ok to not get your way. It&#39;s important to show that you respect others&#39; opinions and concede to try their ideas. If their idea really was wrong it will come out over time and the next time they will be more inclined to trust your view.&lt;/p&gt;
</description>
      <pubDate>Fri, 13 Apr 2018 18:32:26 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2018/how-to-be-a-good-designer/</guid>
    </item>
    <item>
      <title>Lightning Fast Filtering in JavaScript</title>
      <link>https://chrissmith.xyz/blog/2018/lightning-fast-filtering-in-javascript/</link>
      <description>
&lt;article&gt;
  &lt;h1&gt;Lightning Fast Filtering in JavaScript&lt;/h1&gt;
  &lt;div class=&quot;details&quot;&gt; Published &lt;time datetime=&quot;2018-02-01 17:26:27&quot;&gt;1 Feb 2018&lt;/time&gt; &lt;/div&gt;
  &lt;p&gt;I thought I&#39;d share a technique for filtering large sets of data quickly in a web page. The scenario is a biggish
    set of data, 100,000 records, with each record having 3 properties, and we want to filter them using text
    matching.&lt;/p&gt;
  &lt;p&gt;Here is the finished article with dummy generated data. Give it a try. Just type any 3 or 4 characters and watch it
    do its thing.&lt;/p&gt;
  &lt;p class=&quot;codepen&quot; data-height=&quot;600&quot; data-default-tab=&quot;result&quot; data-slug-hash=&quot;mXeMGL&quot; data-user=&quot;chris22smith&quot; style=&quot;
      block-size: 300px;
      box-sizing: border-box;
      display: flex;
      align-items: center;
      justify-content: center;
      border: 2px solid;
      margin: 1em 0;
      padding: 1em;
    &quot;&gt;
    &lt;span&gt;See the Pen
      &lt;a href=&quot;https://codepen.io/chris22smith/pen/mXeMGL&quot;&gt; Fast Filtering with JavaScript&lt;/a&gt;
      by Chris Smith (&lt;a href=&quot;https://codepen.io/chris22smith&quot;&gt;@chris22smith&lt;/a&gt;) on
      &lt;a href=&quot;https://codepen.io/&quot;&gt;CodePen&lt;/a&gt;.&lt;/span&gt;
  &lt;/p&gt;
  &lt;script async=&quot;&quot; src=&quot;https://cpwebassets.codepen.io/assets/embed/ei.js&quot;&gt;&lt;/script&gt;
  &lt;p&gt;Fast, isn&#39;t it? You can go into the JavaScript tab and see how it all works but I&#39;ll explain some of the main
    parts.&lt;/p&gt;
  &lt;p&gt;When trying to make it fast the most important thing to be aware of is that changing JavaScript objects is fast,
    changing the DOM is slow. So, we do as much as we can in JavaScript and then just update the DOM at the end. If you
    try to create 100,000 &amp;lt;li&amp;gt; tags it will be very slow and will probably die on you.&lt;/p&gt;
  &lt;p&gt;The first step is to set up a function to convert the data array into a HTML list. We keep this fast by setting a
    limit on how many items we will show. In this demo I&#39;ve set it to 10 but even increasing it to 100 makes little
    difference to the speed. They key thing is not to get into big numbers which put a strain on the DOM. So we don&#39;t
    loop through all the items, only the first few. A nice small loop, which runs quickly.&lt;/p&gt;
  &lt;p&gt;The building is all done in JavaScript, with nothing touching the DOM until we have a complete Document Fragment
    with all the list items ready to append to our list. I&#39;ve separated out the building of each list item into its own
    function to hopefully make this even faster. Whenever iterating through large numbers of records the more variables
    and functions we can take out of the loop and pre-define the better.&lt;/p&gt;
  &lt;p&gt;The next step is to get the data array with the full data and filter it down into a smaller array using the native
    JavaScript filter() method. This method is incredibly fast, much quicker than using a for loop to iterate through
    each item. You can read more about
    &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;filter() on MDN&lt;/a&gt;. If you use a predefined function with it rather than an anonymous function it&#39;s faster still.&lt;/p&gt;
  &lt;p&gt;Once we have the filtered down array we can call our function to rebuild the list in HTML. It all happens in the
    blink of an eye.&lt;/p&gt;
  &lt;p&gt;As a final touch I&#39;ve added a count message function which gets called each time we filter. This just helps to see
    what&#39;s going on - how many records are being shown and the size of the reduced data set.&lt;/p&gt;
&lt;/article&gt;
</description>
      <pubDate>Thu, 01 Feb 2018 17:26:27 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2018/lightning-fast-filtering-in-javascript/</guid>
    </item>
    <item>
      <title>Accessible Colour Contrast</title>
      <link>https://chrissmith.xyz/blog/2018/accessible-colour-contrast/</link>
      <description>&lt;p&gt;When I started looking at accessibility and using the &lt;a href=&quot;https://www.deque.com/products/axe/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;aXe&lt;/a&gt; accessibility testing tool, one of the first things that it reported was insufficient colour contrast. So, I started looking into it. The page I tested had quite a few different shades of grey (not 50, before anyone else says it) so this seemed like a good place to start.&lt;/p&gt;
&lt;p&gt;How light can grey text be against a white background, or flipped around, how dark does a grey background need to be for white text to be clear?&lt;/p&gt;
&lt;p&gt;And the same with black. How dark can grey text go on a black background and how light does a grey background need to be for black text to be easily legible?&lt;/p&gt;
&lt;p&gt;The results are shown in the embedded pens below. Please share if you find this useful. :)&lt;/p&gt;
&lt;p&gt;[codepen_embed height=&amp;quot;1050&amp;quot; theme_id=&amp;quot;dark&amp;quot; slug_hash=&amp;quot;POxVQg&amp;quot; default_tab=&amp;quot;result&amp;quot; user=&amp;quot;chris22smith&amp;quot;]See the Pen &lt;a href=&quot;https://codepen.io/chris22smith/pen/POxVQg/&quot;&gt;Accessibility - Colour Contrast with White&lt;/a&gt; by Chris Smith (&lt;a href=&quot;https://codepen.io/chris22smith&quot;&gt;@chris22smith&lt;/a&gt;) on &lt;a href=&quot;https://codepen.io/&quot;&gt;CodePen&lt;/a&gt;.[/codepen_embed]&lt;/p&gt;
&lt;p&gt;[codepen_embed height=&amp;quot;1050&amp;quot; theme_id=&amp;quot;dark&amp;quot; slug_hash=&amp;quot;XzGgpM&amp;quot; default_tab=&amp;quot;result&amp;quot; user=&amp;quot;chris22smith&amp;quot;]See the Pen &lt;a href=&quot;https://codepen.io/chris22smith/pen/XzGgpM/&quot;&gt;Accessibility - Colour Contrast with Black&lt;/a&gt; by Chris Smith (&lt;a href=&quot;https://codepen.io/chris22smith&quot;&gt;@chris22smith&lt;/a&gt;) on &lt;a href=&quot;https://codepen.io/&quot;&gt;CodePen&lt;/a&gt;.[/codepen_embed]&lt;/p&gt;
&lt;p&gt;The next task is to find the acceptable contrast blacks and whites for pale greys, like #EEE or #F7F7F7, and dark greys, like #222.&lt;/p&gt;
</description>
      <pubDate>Wed, 10 Jan 2018 19:00:40 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2018/accessible-colour-contrast/</guid>
    </item>
    <item>
      <title>What I Learned in 2017</title>
      <link>https://chrissmith.xyz/blog/2018/what-i-learned-in-2017/</link>
      <description>&lt;p&gt;A bit late but I still feel it&#39;s worth keeping track...&lt;/p&gt;
&lt;p&gt;2017 has been different to previous years. It wasn&#39;t so much about learning new tech and tools as just getting back to basics and doing things better.&lt;/p&gt;
&lt;h3&gt;Simplifying Things&lt;/h3&gt;
I&#39;ve learned to keep things simple and not make them more complicated than they need to be. I actively try to write less JavaScript, doing more with HTML and CSS, and trusting native form controls instead of trying to re-invent them.
&lt;p&gt;A good example might be something like a list of text items where we want the currently selected item to be bold. We could use JavaScript to set the style of the selected item and add click events to change the state of each item but we don&#39;t need to. When we just look at the requirement and what is actually happening, it can be done with a radio button list. Just add radio buttons each with a unique  ID but the same name attribute. Put a label after each referring to it with the for attribute. Finally use CSS to hide the input and apply a style to :checked + label. Done. It&#39;s a radio button list in disguise. Not only is it much simpler code but it&#39;s accessible as a non screen user just sees a standard radio button list.&lt;/p&gt;
&lt;h3&gt;Components&lt;/h3&gt;
In the world of Angular, and starting to explore the more recent versions, I&#39;ve got used to using components. As a front end developer/designer it&#39;s been great to be able to build a small standalone snippet of HTML/CSS in CodePen. By having it small and isolated it makes it easy to test in browsers, linting tools, accessibility tools, etc. It&#39;s like unit testing for functions.
&lt;h3&gt;Sass (SCSS)&lt;/h3&gt;
I came to Sass very late but it hasn&#39;t taken long for it to become the norm and writing standard CSS now just feels weird and like hard work.
&lt;h3&gt;Accessibility&lt;/h3&gt;
In the last couple of months I&#39;ve made a conscious effort to improve accessibility. I&#39;ve started using &lt;a href=&quot;https://www.deque.com/products/axe/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;aXe&lt;/a&gt; accessibility checker and guidance from the Accessibility Project site, &lt;a href=&quot;https://a11yproject.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;a11yproject.com&lt;/a&gt;. It&#39;s a big area and an important one so more about that in another dedicated post.
&lt;h3&gt;Xamarin&lt;/h3&gt;
I&#39;ve dipped my toe into the waters of cross platform development with Xamarin. It allows you write code in C# and export separate versions for iOS, Android and Windows. There&#39;s still some platform specific quirks but it&#39;s about 90% reusable and the framework makes it manageable. It now supports &lt;em&gt;some&lt;/em&gt; CSS too as well as it&#39;s own style rule syntax so should be easier.
&lt;h3&gt;Adobe Illustrator&lt;/h3&gt;
Final one on my list is that I&#39;ve now got Illustrator. I don&#39;t really know what I&#39;m doing yet, still Googling each new thing I need but it&#39;s an amazingly powerful tool. It&#39;s been great for creating alternate versions of logos, converting PNGs to SVG and optimising existing images.
&lt;h3&gt;2018?&lt;/h3&gt;
I&#39;m not sure what 2018 holds. I think I might actually start doing some training, focusing on HTML and CSS.
</description>
      <pubDate>Wed, 10 Jan 2018 17:17:09 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2018/what-i-learned-in-2017/</guid>
    </item>
    <item>
      <title>Native Browser Controls Rule</title>
      <link>https://chrissmith.xyz/blog/2017/native-browser-controls-rule/</link>
      <description>&lt;p&gt;It&#39;s become very common for designers to replace the standard native browser controls with their own custom controls. There are good reasons for this, consistent appearance across browsers and devices being the main one. However, there&#39;s a lot more to consider than just how it looks.&lt;/p&gt;
&lt;h3&gt;Form Controls&lt;/h3&gt;
Let&#39;s think about something like a slider switch in place of a good old fashioned checkbox. It looks cool but...
&lt;p&gt;Is it accessible?
How does it appear to a non screen user?&lt;/p&gt;
&lt;p&gt;Does it have a disabled state?
And a read-only state?
And a focus state?
Do these states all also work for non visual users?&lt;/p&gt;
&lt;p&gt;Can you tab to it?&lt;/p&gt;
&lt;p&gt;Does it go back to its initial state using a form reset?&lt;/p&gt;
&lt;p&gt;Does it work with touch gestures, e.g. swipe left to right?&lt;/p&gt;
&lt;h3&gt;Links&lt;/h3&gt;
Now let&#39;s think about a simple link. It&#39;s pretty common to see icons used with an onclick event instead of links. But its not the same.
&lt;p&gt;How would a user know that it&#39;s an interactive control? Maybe it has a hover state style change but this would not help a non screen user.&lt;/p&gt;
&lt;p&gt;A link (a tag with href attribute) does other things. You can tab to it. On Windows, you can use Ctrl + click to open in a new tab, Shift + click to open in a new window, right click and &amp;quot;Save link as...&amp;quot; (or equivalent) to download the target file. Wrapping the icon in an &lt;a&gt; tag opens up a lot more possibilities.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I&#39;m not saying don&#39;t use your own controls but before replacing native controls think about what you might be sacrificing and make sure you&#39;ve got it all covered.&lt;/p&gt;
</description>
      <pubDate>Fri, 10 Nov 2017 18:00:46 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2017/native-browser-controls-rule/</guid>
    </item>
    <item>
      <title>Do IT Qualifications Hold Value?</title>
      <link>https://chrissmith.xyz/blog/2017/do-it-qualifications-hold-value/</link>
      <description>&lt;p&gt;I work in tech, software development. I&#39;d say that of the developers I have worked with, some have clear IT backgrounds, e.g. Computer Science degrees, others are entirely self-taught. As far as I can tell, as long as they have enough experience, it doesn&#39;t seem to make a lot of difference. Controversial?&lt;/p&gt;
&lt;p&gt;Being self-taught myself, I&#39;m not actually sure what is taught in school and universities but, from my limited experience of working in a college and from knowing what my kids learn, it feels like it&#39;s always well being the curve, at least 2 or 3 years behind what&#39;s being used in the industry. This is both in terms of tooling and approach.&lt;/p&gt;
&lt;p&gt;My kids have recently been learning to do various tasks in Excel. They&#39;ll spend a week on something that I feel could be picked up in a couple of hours. For me, you&#39;d get a lot more out of Excel by investing time in learning mathematical functions. And learning to use the import/export functionality. But that side of things is never taught.&lt;/p&gt;
&lt;p&gt;Lots of courses include modules on the history of computing, the Difference Engine. Whilst interesting, does it really help? In fact, I&#39;m not sure that any time spent on how things used to be done is really very useful. Keep looking forwards, not backwards.&lt;/p&gt;
&lt;p&gt;I&#39;m not sure what employers look for now or will look for in the future but I feel there could be more value in other subjects like maths than IT. IT is too broad, too &amp;quot;Jack of all trades, master of none&amp;quot;, and without any depth lacks real value. It&#39;s easy to teach yourself whatever you need to learn in IT - there are so many good quality resources. I&#39;d be inclined to learn other things and then demonstrate your IT skills through your own projects - websites, apps, APIs, etc. This will not only let you develop your other skills but give you experience of being self-sufficient in tech. It will also prove you have the motivation and discipline to teach yourself, which I think is essential.&lt;/p&gt;
&lt;p&gt;Just my view. Please feel free to argue the case for the quals...&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
</description>
      <pubDate>Wed, 25 Oct 2017 18:30:16 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2017/do-it-qualifications-hold-value/</guid>
    </item>
    <item>
      <title>Shared User Accounts</title>
      <link>https://chrissmith.xyz/blog/2017/shared-user-accounts/</link>
      <description>&lt;p&gt;I live with my wife and two boys and as you&#39;d expect we have lots of accounts for lots of different services. What&#39;s odd is that the models for the accounts vary quite considerably.&lt;/p&gt;
&lt;p&gt;For banking, gas, electricity and water my wife and I have joint accounts - we are jointly responsible and either of us can make changes. Where they offer online services, we each have our own login but are presented with exactly the same data. It&#39;s quite a standard user setup from a system point of view.&lt;/p&gt;
&lt;p&gt;A lot of online only services still work on a single one account one person basis. We use Amazon Prime. We&#39;ve both had Amazon accounts for years but when it comes to upgrading to Prime we&#39;re not both going to pay the premium. And if we want to read the same Kindle ebook we&#39;re not going to buy it twice. So, we end up using the one account and Amazon, who are famous for their user behaviour tracking and algorithms, lose sight of one of their users and what&#39;s really happening. That can&#39;t be good for them either.&lt;/p&gt;
&lt;p&gt;Both Microsoft and Netflix seem to have recognised the need for shared family accounts - it&#39;s one subscription per household, not one per person. You set up each user with their own login and they can then save their own favourites, watch lists, game progress, etc. It also allows parental control over children. It&#39;s secure too - limited to a single local network so you can&#39;t go giving access to anyone outside of that.&lt;/p&gt;
&lt;p&gt;I think more services need to recognise how things are really used and adapt their account models to fit. We need special accounts for couples, families, work teams, businesses, charities, etc.&lt;/p&gt;
</description>
      <pubDate>Sun, 22 Oct 2017 14:00:47 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2017/shared-user-accounts/</guid>
    </item>
    <item>
      <title>Setting Performance Targets</title>
      <link>https://chrissmith.xyz/blog/2017/setting-performance-targets/</link>
      <description>&lt;p&gt;I sometimes read things like &amp;quot;A user will abandon a page if it doesn&#39;t load within 2 seconds&amp;quot;. I really don&#39;t think these kinds of generalisations are very helpful.&lt;/p&gt;
&lt;p&gt;Users&#39; expectations vary. They take account of network connectivity and the nature of the information they&#39;re accessing. If I abandoned any requests that were not fulfilled within 2 seconds I don&#39;t think I&#39;d ever see any web pages on my phone. My expectations aren&#39;t that high. I know it&#39;s going to take longer and that&#39;s fine, up to a point.&lt;/p&gt;
&lt;p&gt;So, are there benchmarks that we can aim for realistically? We can&#39;t just say &amp;quot;page&amp;quot; and &amp;quot;2 seconds&amp;quot;. It needs to also specify the network connection type - wired, WiFi, 3G, 4G, and the page weight in bytes.&lt;/p&gt;
&lt;p&gt;There&#39;s a danger that we strive to keep everything small and light and then give poor experiences on wired desktops with super fast connection speeds. We need to deliver the appropriate experiences.&lt;/p&gt;
&lt;p&gt;What&#39;s our definition of &amp;quot;loaded&amp;quot;? Is it when everything is there and available to use? As soon as there&#39;s something to interact with? A sign that something&#39;s happening? A use doesn&#39;t necessarily need it all. They just need to know that it&#39;s coming within a reasonable time frame. There are lots of tactics for keeping a user on side while content is loading too - an entertaining loading animation, flashing up a quote, animating in the various screen elements. As long as there&#39;s something to keep the mind from wandering onto something else it&#39;s generally fine. Does this distraction tactic feel great the first time but really irritate by the tenth time?&lt;/p&gt;
&lt;p&gt;How do you benchmark all of that? It&#39;s hard, very hard. Maybe that why all we&#39;ve got is empty generalisations?&lt;/p&gt;
</description>
      <pubDate>Fri, 20 Oct 2017 17:30:27 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2017/setting-performance-targets/</guid>
    </item>
    <item>
      <title>To DOM or Not to DOM?</title>
      <link>https://chrissmith.xyz/blog/2017/to-dom-or-not-to-dom/</link>
      <description>&lt;p&gt;I&#39;m trying to work out when it&#39;s best to put attributes in the DOM and when it&#39;s best to just leave them in JavaScript objects. This is going to be hard to explain so bear with me.&lt;/p&gt;
&lt;p&gt;Let&#39;s suppose we have a list of users on a page. Each user has a number of properties, not things we&#39;d display like name, age and gender but hidden things like permissions, e.g. isAdmin, canComment, isManager, etc. These properties are going to be used in logic to determine how things are displayed on screen - maybe an extra bit of detail or an icon. Just as an example, if canComment is true then a speech bubble icon will appear.&lt;/p&gt;
&lt;p&gt;The basic HTML might look something like this:&lt;/p&gt;
&lt;pre&gt;&amp;lt;ul&amp;gt;
  &amp;lt;li id=&quot;001&quot; class=&quot;user&quot;&amp;gt;John&amp;lt;/li&amp;gt;
  &amp;lt;li id=&quot;002&quot; class=&quot;user&quot;&amp;gt;Paul&amp;lt;/li&amp;gt;
  &amp;lt;li id=&quot;003&quot; class=&quot;user&quot;&amp;gt;George&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Behind this is a JavaScript object, like this:&lt;/p&gt;
&lt;pre&gt;var users = [
  {
    id: &#39;001&#39;,
    name: &#39;John&#39;,
    canComment: true
  },
  {
    id: &#39;002&#39;,
    name: &#39;Paul&#39;,
    canComment: false
  },
  {
    id: &#39;003&#39;,
    name: &#39;George&#39;,
    canComment: false
  }
];
&lt;/pre&gt;
&lt;p&gt;So, user John is allowed to comment and we want to show an icon. There are 2 approaches:&lt;/p&gt;
&lt;ol&gt;
 	&lt;li&gt;
&lt;h3&gt;Use the DOM&lt;/h3&gt;
We could add the icon inside each &amp;lt;li&amp;gt; and then add a class (class=&quot;user can-edit&quot;) or a data-attribute (data-can-edit) to the &amp;lt;li&amp;gt; and use CSS to display it as appropriate, e.g. .user[data-can-edit] .icon { display: inline-block }.&lt;/li&gt;
 	&lt;li&gt;
&lt;h3&gt;Use JavaScript&lt;/h3&gt;
Or, we could write a JavaScript function to filter the objects to just those with canComment set to true, get their ids, and then loop through the list items adding the icon HTML when the ids match the filtered list.&lt;/li&gt;
&lt;/ol&gt;
The first approach puts the property into the DOM, puts the icon into the DOM and then uses CSS to show/hide it. It feels easy. The icon is always sat there waiting, like an unchecked checkbox, only shown when needed (checked). There is still logic but it&#39;s done up front. The DOM is actually human readable and it&#39;s easy to see which users can and can&#39;t edit for debugging purposes. I see this approach used a lot, including the hidden DOM elements, usually because of the way templates or components are used. It&#39;s easier to include it and pass a property to toggle whether or not it displays. It also means that if we want to change the property during the lifecycle of the page, e.g. take away John&#39;s commenting permission, it&#39;s minimal change to the DOM.
&lt;p&gt;The second approach only touches the DOM to insert the icon where needed. It does all the logic in JavaScript and the output in the DOM reflects what the user actually sees on screen. There are no hidden elements. This has advantages when it&#39;s scaled up, in that it keeps the DOM lighter and there&#39;s no waste. The JavaScript is incredibly fast in modern browsers so the functions won&#39;t slow anything down, especially if using .filter(), map(), etc. The trick here is not to loop through and add the icons one at a time but to run through building the whole list and just doing the one insert or replace operation. This makes the DOM less readable as all the canComment data is in JavaScript.&lt;/p&gt;
&lt;p&gt;So, is it better to use the DOM for data or keep it in JavaScript?&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
</description>
      <pubDate>Sun, 15 Oct 2017 12:00:11 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2017/to-dom-or-not-to-dom/</guid>
    </item>
    <item>
      <title>Speed, Usability and Speed</title>
      <link>https://chrissmith.xyz/blog/2017/speed-usability-and-speed/</link>
      <description>&lt;p&gt;When looking at making UX improvements to web apps, I tend to obsess about speed and performance. For me a fast experience is a good experience.&lt;/p&gt;
&lt;p&gt;I really think that speed outweighs all other factors. If you can keep all loading and waiting times very short, ideally under a second, it keeps the user engaged and efficient in what they&#39;re trying to achieve. As soon as anything takes longer than a couple of seconds it&#39;s easy to let your mind wander, switch context and then take longer to get back into what you were doing. If this is happening lots of times across a lengthy session it really adds up, not to mention the frustration it causes.&lt;/p&gt;
&lt;p&gt;Usability is obviously important too. It needs to be obvious what screen elements you can interact with - is that an underlined heading or a link? It needs to be clear what an interaction with that element will do. Unexpected behaviour makes people feel uneasy and suspicious about other potential interactions. And it&#39;s always good if the user can see how the whole piece fits together, how you get from A to B, B to C, etc.&lt;/p&gt;
&lt;p&gt;The usual causes of things being slow are not network issues but bad design. The most common problem is simply trying to send too much too soon. Requirements often ask for a high number of items to be displayed with a high level of detail against each. It&#39;s always worth asking if this can be broken down to show fewer items or less detail with more being available on demand.&lt;/p&gt;
&lt;p&gt;If a screen lists 20 items with all their details and it&#39;s taking 5 seconds to load we still don&#39;t have to load it all at once. Rather than the user waiting for 5 seconds, why not just load the first 3 items quickly, so the user has something to see within a more acceptable time frame (before the mind wanders), and then load the other 17 in the background while the first 3 are keeping them occupied.&lt;/p&gt;
&lt;p&gt;Even if your app is working at acceptable speeds if you haven&#39;t already done so you should still try to make it faster. Use a strategy for how you&#39;re going to load new data and use the usual performance tricks - caching, bundling, minification, pre-fetching - to really give the UX a boost.&lt;/p&gt;
</description>
      <pubDate>Sat, 14 Oct 2017 11:22:28 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2017/speed-usability-and-speed/</guid>
    </item>
    <item>
      <title>Component World</title>
      <link>https://chrissmith.xyz/blog/2017/component-world/</link>
      <description>&lt;p&gt;Whatever stack of framework you use, everything in web development seems to be going modular. We&#39;re no longer building pages of screens but components and component systems. This is changing the way I work with files. Where once I would have combined my script and styles into a single resource to reduce requests, I now actively look to break everything down into tiny pieces. For example, I have loads of Sass files. These get compiled into CSS before being concatenated and minified - turned back into the single big file. Working this way has several advantages. It&#39;s easier to work in smaller files - easy to find the line you need with minimal scrolling. It paves the way for using web components of a component system where styles of scripts can be embedded within the component, making it a true standalone piece of the document. Finally, it makes it easy to build dependency free components in a tool like CodePen. You can just write the HTML, Sass and JavaScript and save it as an isolated component with its own demo.&lt;/p&gt;
</description>
      <pubDate>Sat, 09 Sep 2017 18:08:39 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2017/component-world/</guid>
    </item>
    <item>
      <title>Different Conditional Syntaxes in JavaScript</title>
      <link>https://chrissmith.xyz/blog/2017/different-conditional-syntaxes-in-javascript/</link>
      <description>&lt;p&gt;There are a few ways of using conditionals in JavaScript. I&#39;ve started thinking about it again as I&#39;ve just discovered another new way.&lt;/p&gt;
&lt;p&gt;Lets start off with some basic set up stuff for our examples - a variable, which can be true or false and functions to use in either case:&lt;/p&gt;
&lt;pre&gt;var isAllowed = false;

function admit() {
  console.log(&quot;admitted&quot;);
}

function reject() {
  console.log(&quot;rejected&quot;);
}
&lt;/pre&gt;
&lt;p&gt;The first way I learned to write a conditional, which I consider the classic way, is with if and else clauses like this:&lt;/p&gt;
&lt;pre&gt;if (isAllowed) {
  admit();
} else {
  reject();
}
&lt;/pre&gt;
&lt;p&gt;If you don&#39;t need the else part, you can do it in one line, leaving out the curly braces like this:&lt;/p&gt;
&lt;pre&gt;if (isAllowed) admit();
&lt;/pre&gt;
&lt;p&gt;Another way of writing it is to use a ternary operator. The first part before the question mark is evaluated. If it&#39;s true the next part between the question mark and colon is used; if false the last part after the colon is used:&lt;/p&gt;
&lt;pre&gt;isAllowed ? admit() : reject();
&lt;/pre&gt;
&lt;p&gt;If you want this style of expression, without actually writing &amp;quot;if&amp;quot; but you don&#39;t want the else part there is yet another way.&lt;/p&gt;
&lt;p&gt;Look at this:&lt;/p&gt;
&lt;pre&gt;!isAllowed || admit();
&lt;/pre&gt;
&lt;p&gt;Weird, eh? With an OR expression using ||, the first part is evaluated or run if a function. If true it stops there. If false it evaluates or runs the second part. In case you&#39;re new to this, the ! means NOT or inverts the meaning. So, we&#39;re saying if isAllowed is false, stop; otherwise run the admit() function.&lt;/p&gt;
&lt;p&gt;It&#39;s the same technique often used to set default values, just turned around:&lt;/p&gt;
&lt;pre&gt;var carModel = getCarModel() || &#39;unknown&#39;;
&lt;/pre&gt;
&lt;p&gt;If you&#39;re free to use any of these I&#39;d probably advise sticking to the classic if (else) with the braces. It&#39;s so much more readable and can be understood by a developer at any level. I like the last technique but I&#39;d only use it in solo projects or where I can&#39;t use anything else.&lt;/p&gt;
</description>
      <pubDate>Thu, 22 Jun 2017 18:00:19 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2017/different-conditional-syntaxes-in-javascript/</guid>
    </item>
    <item>
      <title>Hacking Borders</title>
      <link>https://chrissmith.xyz/blog/2017/hacking-borders/</link>
      <description>&lt;p&gt;Have you ever been in a situation where your borders aren&#39;t rendering as expected? Hopefully not.&lt;/p&gt;
&lt;p&gt;I&#39;ve hit this issue recently using PhantomJS to turn HTML content into a PDF. It generally works pretty well but when you get into tables with collapsed borders and use rowspan and colspan things start getting a bit hairy and some of your borders just don&#39;t get rendered. Sad face.&lt;/p&gt;
&lt;p&gt;No amount of messing with border-collapse, display or border properties seems to have any affect. So, what can we do? Time to get dirty and hack our way out of it. Surgical gloves on.&lt;/p&gt;
&lt;p&gt;We can&#39;t change the borders so we create pseudo borders. We use CSS pseudo elements to create lines within the cells. Here&#39;s the CSS for a top-border:&lt;/p&gt;
&lt;pre&gt;.hacked-border-top {
  position:relative;
}

.hacked-border-top:before {
  background-color:currentColor; /* or whatever */
  height:1px;
  left:0;
  position:absolute;
  top:-1px;
  width:100%;
}
&lt;/pre&gt;
&lt;p&gt;The pseudo border is absolutely positioned within the cell, thickness (height) 1px, full width. The top:-1px moves it outside the box model to where the border would be.&lt;/p&gt;
&lt;p&gt;Change the height, width and bottom, left, right and top values as need be for the different sides.&lt;/p&gt;
&lt;p&gt;Please only use this as a last resort when all else fails.&lt;/p&gt;
&lt;div style=&quot;border: solid .5em #c00; border-radius: 1em; color: #c00; display: inline-block; font-family: sans-serif; font-weight: bold; margin: 1em; padding: 1em; text-transform: uppercase;&quot;&gt;In case of emergency break glass&lt;/div&gt;
</description>
      <pubDate>Wed, 21 Jun 2017 18:00:52 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2017/hacking-borders/</guid>
    </item>
    <item>
      <title>Take a Tour</title>
      <link>https://chrissmith.xyz/blog/2017/take-a-tour/</link>
      <description>&lt;p&gt;When working with web apps or more complex sites where the user has to work through a process a product tour can be a very useful addition. In case it&#39;s not clear from the name (I&#39;m not sure I&#39;d have known) a product tour is basically a series of tooltips which appear and guide the user through using the page/app in steps.&lt;/p&gt;
&lt;p&gt;Having the help or guidance right there in the page is much neater than providing a separate help page or subsite. It&#39;s not always easy flicking back and forth between the screen your working on and the documentation.&lt;/p&gt;
&lt;p&gt;The other great benefit is that you don&#39;t have to just show the tooltips as hints. You can actually tell the user what to do and the tour advances as they do it. So, they&#39;re actually using your site and you&#39;re helping them through it.&lt;/p&gt;
&lt;p&gt;If implemented well this could mean the end of lengthy, hard to maintain documentation, training materials, videos, etc.&lt;/p&gt;
&lt;p&gt;There are a few libraries out there for this but, of the ones I&#39;ve looked at, the best for my needs was &lt;a href=&quot;https://linkedin.github.io/hopscotch/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Hopscotch&lt;/a&gt; by LinkedIn. It&#39;s vanilla JavaScript, very simple to implement and has some nice added features like support for other languages.&lt;/p&gt;
&lt;p&gt;You define a tour object with an array of steps. Each step then has an element selector, the bubble content and the position where you want it to appear - top, bottom, left, right. That&#39;s it.&lt;/p&gt;
&lt;p&gt;You can also do some pretty clever stuff where your tour goes across multiple pages. This just needs you to pass the tour ID and step index so it knows where to pick up from.&lt;/p&gt;
&lt;p&gt;The Hopscotch demo page explains it all very nicely:
&lt;a href=&quot;https://linkedin.github.io/hopscotch/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;https://linkedin.github.io/hopscotch/&lt;/a&gt;&lt;/p&gt;
</description>
      <pubDate>Wed, 24 May 2017 18:00:48 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2017/take-a-tour/</guid>
    </item>
    <item>
      <title>Why It&#39;s Still Worth Learning Bootstrap</title>
      <link>https://chrissmith.xyz/blog/2017/why-its-still-worth-learning-bootstrap/</link>
      <description>&lt;p&gt;Until fairly recently I didn&#39;t like UI frameworks. I always felt that they would only ever handle half of what the developer actually needed and added a lot of extra unused bulk to the load. Whilst that it still true, to a degree, I now think that there are enough reasons to use a framework which outweigh this concern.&lt;/p&gt;
&lt;h3&gt;Maintainability&lt;/h3&gt;
Adopting a framework isn&#39;t just about the code and the styling. It&#39;s about using a well established pattern and way of doing things. The big win for me is that the documentation is all out there. I don&#39;t have to write it. So, if I come back to a page in a year&#39;s time I&#39;ll understand how I&#39;ve structured the layout. This is also a massive benefit when working with other developers. Having a common standard and style makes it easier for anyone to pick up anyone else&#39;s code.
&lt;h3&gt;Consistency&lt;/h3&gt;
Having an opinionated way of doing things ensures that pages within a site are consistent. It&#39;s very easy, especially in a large site, to have 3 different ways of doing columns, e.g. floats, display:table and flexbox. &lt;a href=&quot;https://getbootstrap.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Bootstrap&lt;/a&gt; helps guide developers towards a common preferred approach.
&lt;h3&gt;Accessibility&lt;/h3&gt;
Historically I&#39;m not sure &lt;a href=&quot;https://getbootstrap.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Bootstrap&lt;/a&gt; has had the best reputation for accessibility but these days it seems pretty solid. Most of the examples in the documentation show things like roles and screen reader only content (.sr-only), which I probably wouldn&#39;t have considered writing my own HTML.
&lt;h3&gt;Efficiency&lt;/h3&gt;
Using a framework means I&#39;m not spending time solving solved problems. It means other people have already invested the time in finding a good way of doing something so that I don&#39;t have to. It provides a way of handling most responsive design issues. It may not always be perfect but if you&#39;re in a hurry you&#39;ve got something to work with from the off. I believe that this can really speed up development.
&lt;h3&gt;Understanding&lt;/h3&gt;
Learning a framework like &lt;a href=&quot;https://getbootstrap.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Bootstrap&lt;/a&gt; teaches you how a framework hangs together so you can write your own. It&#39;s very useful to understand what components and utility classes might be needed, how you can combine page elements in containers and how you keep it all maintainable.
&lt;h3&gt;Why Bootstrap?&lt;/h3&gt;
Personally, out of all the available UI frameworks, I&#39;d reach for &lt;a href=&quot;https://getbootstrap.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Bootstrap&lt;/a&gt;. It&#39;s the biggest and the best documented (official docs and things like &lt;a href=&quot;https://stackoverflow.com/questions/tagged/twitter-bootstrap&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Stack Overflow&lt;/a&gt; posts). Don&#39;t be put off by the look and feel if this is not what you&#39;re looking for. It&#39;s easy to customise in another layer to look how you want but it does all the layout heavy lifting for you. It&#39;s so widely used that if you use a &lt;abbr title=&quot;Content Delivery Network&quot;&gt;CDN&lt;/abbr&gt; there&#39;s a good chance the user will already have it all cached so it&#39;ll load quickly.
</description>
      <pubDate>Fri, 19 May 2017 18:00:29 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2017/why-its-still-worth-learning-bootstrap/</guid>
    </item>
    <item>
      <title>Presenting Multiple Layouts</title>
      <link>https://chrissmith.xyz/blog/2017/presenting-multiple-layouts/</link>
      <description>&lt;p&gt;I&#39;m sure everyone has seen web apps where the user is given a choice of layouts for their data. Sometimes you can view items as a list or as cards and there&#39;s a mechanism of flipping between them. Gmail has options of Comfortable, Cosy or Compact.&lt;/p&gt;
&lt;p&gt;From the developer&#39;s point of view, it seems like a nice little extra. It&#39;s fairly easy to do in CSS - just toggle a root class on the module and set your styles for each layout.&lt;/p&gt;
&lt;p&gt;Having done this a few times now, my advice would be a pretty emphatic &lt;strong&gt;don&#39;t!&lt;/strong&gt; It starts off as a simple variation but it means that every time you make a small change to the content or layout in one layout you have to do this development for each, and then test in each. In short it multiplies out the work.&lt;/p&gt;
&lt;p&gt;Imagine offering the user a choice of 3 layouts and 3 colour themes. That&#39;s 9 scenarios for the poor tester to check every time you make even the slightest tweak.&lt;/p&gt;
&lt;p&gt;There&#39;s nothing wrong with putting work into a UI but in this case the benefit to the end user is negligible for a lot of additional effort. It would be far better to spend the time just doing one layout really well.&lt;/p&gt;
&lt;p&gt;I think there can be occasions where it can work, like just toggling a module font size or line-height but getting into different sets of styling rules is a big no-no for me.&lt;/p&gt;
</description>
      <pubDate>Fri, 05 May 2017 18:00:02 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2017/presenting-multiple-layouts/</guid>
    </item>
    <item>
      <title>Measuring Front End Performance</title>
      <link>https://chrissmith.xyz/blog/2017/measuring-front-end-performance/</link>
      <description>&lt;p&gt;My last post was about &lt;a href=&quot;https://chrissmith.xyz/front-end-performance-enhancements&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Front End Performance Enhancements&lt;/a&gt; and how I&#39;ve managed to improve page load times on a site. I&#39;ve recently done some work in this area and, whilst I&#39;m satisfied that my changes have improved performance, I can&#39;t really be sure to what extent.&lt;/p&gt;
&lt;p&gt;With any kind of improvement work it&#39;s always nice to have a before and after and be able to show the difference. If this can be hard numbers, like in sales, then even better. With web performance can we ever really rely on any numbers?&lt;/p&gt;
&lt;p&gt;I&#39;ve been using Google Analytics Page Timing reports, specifically the Page Speed Suggestions report, which gives the most popular pages (sorted by page views) and the load time in seconds. I&#39;ve tried comparing a week before my changes with a week after them. The page load times are different and generally better but it&#39;s hard to know if I&#39;m really comparing like with like.&lt;/p&gt;
&lt;p&gt;There are so many random factors. The number of page views is different for the two different periods. We don&#39;t know who the users are, and therefore how much data they&#39;re loading. We don&#39;t know their locations or devices or their network connection speed. We can find most of this out but then we&#39;d have to find a way of putting it back together in a fair and meaningful way whilst probably still having some unknowns.&lt;/p&gt;
&lt;p&gt;The other issue is that the page load times in Google Analytics are (mean) averages. This means that one extremely slow load can make the average rocket upwards. Conversely, one user hammering the refresh button and getting lots of page views from the cache will make it drop.&lt;/p&gt;
&lt;p&gt;I think that there are 2 ways we can help to measure performance more accurately.&lt;/p&gt;
&lt;p&gt;The first is just to look at page load times in these reports but wait until we have a larger sample size. As the sample size grows the anomalies are more likely to be diluted and have less of a sway on the overall result. If possible, try to isolate the extreme results, like the fastest and slowest 5%, and remove these from the averages.&lt;/p&gt;
&lt;p&gt;The second is to use automated load testing so that we&#39;re using very similar conditions for each test. Even in this case we&#39;d have to load the page a few thousand times to get a meaningful average result.&lt;/p&gt;
</description>
      <pubDate>Wed, 03 May 2017 18:00:53 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2017/measuring-front-end-performance/</guid>
    </item>
    <item>
      <title>Front End Performance Enhancements</title>
      <link>https://chrissmith.xyz/blog/2017/front-end-performance-enhancements/</link>
      <description>&lt;p&gt;I&#39;ve recently made a load of changes to a site to improve the page loading times. Now that I&#39;m happy it&#39;s worked I thought I&#39;d share some of the moves. Broadly, we&#39;re looking to load up fewer files and to make each file as small as possible.&lt;/p&gt;
&lt;h3&gt;Remove Inline Content&lt;/h3&gt;
My first step was to get rid of any inline styling or scripting, moving as much as possible into .css or .js files so they are recognised as static resources and cached. Moving &amp;lt;style&amp;gt; blocks out into new CSS files or &amp;lt;script&amp;gt; to JavaScript files is pretty straightforward.
&lt;p&gt;I came across a few instances where these are using some server side binding, something like this:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&amp;lt;script&amp;gt;
  // lots of code
  user.companyName = &#39;@CompanyName&#39;;
  // lots of code
&amp;lt;/script&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Here, @CompanyName is coming from the server. This doesn&#39;t mean that the whole script block has to stay in the HTML. It&#39;s easy to just pull out any server data and stick it in a variable and then move everything else to an external file. Like this:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&amp;lt;script&amp;gt;
  var companyName = &#39;@CompanyName&#39;;
&amp;lt;/script&amp;gt;
&amp;lt;script src=&quot;lots-of-code.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Now the bulk of the code can be cached.&lt;/p&gt;
&lt;h3&gt;Concatenation&lt;/h3&gt;
The next step was to reduce http requests by combining files. You can manually copy all of the CSS or JavaScript into a single file but it&#39;s much more practical to do this with a task runner, like Gulp or Grunt. In ASP.NET there&#39;s a handy RegisterBundles method which combines files into a single resource for you.
&lt;h3&gt;Minification&lt;/h3&gt;
As well as reducing the number of files we can also reduce the size of files. Minification removes whitespace and comments and often optimises repeated code like variable names to make the file as small as possible. This can be done in a task runner too. In ASP.NET it&#39;s an option within bundling - BundlesTable.EnableOptimizations = true.
&lt;h3&gt;Prefetching&lt;/h3&gt;
Prefetching is basically going and getting resources and putting them in the cache ready for future use. You just tell your page which resources to get and when it&#39;s idle it gets them asynchronously. This means you&#39;re shifting the load from your second page onto your first page but without ever affecting the user&#39;s experience. The trick is knowing what page he/she will go to next and loading the appropriate resources and trying to avoid loading things which will not be needed. It&#39;s particularly effective on stepped processes or wizards.
&lt;p&gt;The sites I&#39;ve been working on had a very light login screen, which upon success takes you to a dashboard. As I knew where the user would be going next it meant that I could prefetch the resources. Obviously I couldn&#39;t prefetch anything sensitive that required the user to be logged, like API calls, in but it did mean I could have all of the site wide JavaScript libraries and CSS ready to go. Here&#39;s how it looks in the HTML:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&amp;lt;link rel=&quot;prefetch&quot; href=&quot;~/bundles/GlobalJS&quot;&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Easy, right? As you can see, here I&#39;m prefetching my global JavaScript bundle or concatenated and minified JavaScript resource.&lt;/p&gt;
&lt;p&gt;The site structure was a series of list pages which each have their own details page to view a record in more detail. I made the assumption that if a user navigated to a list page he/she had the intention of viewing a record. So, from the list page I prefetched the resources needed for the details page.&lt;/p&gt;
&lt;p&gt;There&#39;s a great article on &lt;a href=&quot;https://css-tricks.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;CSS Tricks&lt;/a&gt; which goes into far more detail - &lt;a href=&quot;https://css-tricks.com/prefetching-preloading-prebrowsing/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Prefetching, preloading, prebrowsing&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Instant&lt;/h3&gt;
Looking at the Page Timings in Google Analytics almost all pages have reduced loading times, some are now even instant. They have no resources to load as everything is already cached. There&#39;s still some client side processing to be done after load but I&#39;m happy I&#39;ve managed to take away most of the user&#39;s waiting time.
</description>
      <pubDate>Mon, 01 May 2017 13:00:40 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2017/front-end-performance-enhancements/</guid>
    </item>
    <item>
      <title>Precision Level in CSS</title>
      <link>https://chrissmith.xyz/blog/2017/precision-level-in-css/</link>
      <description>&lt;p&gt;When we&#39;re using relative sizing in CSS, percentages or ems, how precise do we need to be with our fractions? Is there an optimum level?&lt;/p&gt;
&lt;p&gt;If we have a font size of 18px (or anything, it&#39;s relative after all) and we want some smaller text at two thirds of its size (12px) then we can express this as .6666666667em or 66.6666666667%. Here I&#39;ve used 10 decimal places to give a very precise fraction but this feels like overkill to me. If I used just 2 decimal places, .67em or 66.67%, is this accurate enough to consistently calculate the desired pixel value. Or should I not worry? It&#39;ll be near enough.&lt;/p&gt;
&lt;p&gt;Looking at other developers&#39; CSS, mainly in tutorials, the general pattern seems to be to use between 4 and 6 decimal places. Looking back through my own code, my preference seems to be to use 6 but I couldn&#39;t tell you why. I&#39;d imagine I&#39;ve just adopted someone else&#39;s coding style. I definitely feel that going beyond 6 seems unnecessary but am not sure how little I can get away with.&lt;/p&gt;
&lt;p&gt;Sass is able to perform calculations using fractions. Here&#39;s an example:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;$two_thirds: 2/3 * 1em;

.smaller {
  font-size: $two_thirds;
}
&lt;/pre&gt;
&lt;p&gt;This resolves to .66667em, 5 decimal places. Is this a set precision or did Sass actually calculate it from the root size and decide what precision was needed for it to resolve to an integer? Hmm (rubs chin). I guess that most people let Sass handle this for them and don&#39;t even look at the compiled CSS.&lt;/p&gt;
</description>
      <pubDate>Fri, 28 Apr 2017 18:00:52 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2017/precision-level-in-css/</guid>
    </item>
    <item>
      <title>The Welsh Language Conundrum</title>
      <link>https://chrissmith.xyz/blog/2017/the-welsh-language-conundrum/</link>
      <description>&lt;p&gt;Presenting content in two or more languages is pretty much a solved problem. The most common way to handle it is to have a language switcher and allow users to flip from a page in one language to the same page content in another language at any point.&lt;/p&gt;
&lt;p&gt;The print world&#39;s equivalent would be putting one language on one side of a sheet of paper and the other language on the other. And then maybe putting a small note about the other language being on the reverse. Both are equal and easy to read, free from the distraction of the other language.&lt;/p&gt;
&lt;p&gt;But what if you want both? There are cases where it&#39;s preferable to keep both languages visible. In Wales the Welsh language is spoken by roughly 1 in 5 people. It was slowly dying out but the government has invested a considerable amount of effort and money into keeping it alive. One of the ways this is done is to keep its profile as high as possible. It should be normal to see Welsh everywhere in Wales. This carries across into digital content too.&lt;/p&gt;
&lt;p&gt;In print the answer is to display content in 2 columns, one Welsh, one English. Typically, as we read left to right, the Welsh is put first so it is at least acknowledged before non Welsh speaking readers can skip across to the English. It works.&lt;/p&gt;
&lt;p&gt;How do we do this on the web? Not quite so easy.&lt;/p&gt;
&lt;p&gt;Can we or should we have mixed language content in pages? Does this go against web standards or is it acceptable if done in the right way?&lt;/p&gt;
&lt;p&gt;We could present a two column layout like in print but then how do we accommodate this on a small screen, like on mobile? Two very narrow columns will give a terrible user experience. If we were to put one above the other, the second language could be pushed a long way down.&lt;/p&gt;
&lt;p&gt;Could we show just the page titles or headings in both languages and then reveal the content in the selected language on click/touch? Possibly. Probably not good for &lt;abbr title=&quot;search engine optimisation&quot;&gt;SEO&lt;/abbr&gt; but maybe it&#39;s not possible to have everything.&lt;/p&gt;
&lt;p&gt;I&#39;ve used a technique previously where I keep the 2 separate language pages but intercept the request and show a full page, like an interstitial ad, which shows the page title and teaser text in both languages. Clicking either redirects to the content in the appropriate language. I refer to it as a &amp;quot;splash page&amp;quot; but I&#39;m not sure if this is the right term.&lt;/p&gt;
&lt;p&gt;Are there any other options I haven&#39;t considered? Please add a comment or &lt;a href=&quot;https://twitter.com/chris22smith&quot; target=&quot;_blank&quot;&gt;contact me on twitter&lt;/a&gt;.&lt;/p&gt;
</description>
      <pubDate>Fri, 07 Apr 2017 17:21:41 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2017/the-welsh-language-conundrum/</guid>
    </item>
    <item>
      <title>Pet Hate: Click Here</title>
      <link>https://chrissmith.xyz/blog/2017/pet-hate-click-here/</link>
      <description>&lt;p&gt;I hate seeing &amp;quot;click here&amp;quot;. Uuurgh! It&#39;s such a 1995 way of thinking about web pages. There&#39;s always a better way.&lt;/p&gt;
&lt;p&gt;A typical example might be &amp;quot;To create your account please click here.&amp;quot; Why not simply &amp;quot;Create your account&amp;quot;? It&#39;s obvious, it&#39;s shorter and the link text actually means something which is better for accessibility and search engine optimisation.&lt;/p&gt;
&lt;p&gt;The other part that annoys me is that a click isn&#39;t really a click any more. It could be a tap on a touch screen, you might be tabbing through the interactive page elements with a keyboard, using a screen reader or any number of other devices which don&#39;t use a click.&lt;/p&gt;
&lt;p&gt;If you see it, please have a word. :)&lt;/p&gt;
</description>
      <pubDate>Sun, 19 Mar 2017 18:38:49 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2017/pet-hate-click-here/</guid>
    </item>
    <item>
      <title>HTML Semantics - Header or Sidebar?</title>
      <link>https://chrissmith.xyz/blog/2017/html-semantics-header-or-sidebar/</link>
      <description>&lt;p&gt;Here&#39;s a question on HTML semantics. We now have the not-so-new HTML5 semantic sectioning elements which define areas of the page and try to bring more meaning to it. This is generally seen as a step forward from using &amp;lt;div&amp;gt; which has no particular meaning. Does it always work?&lt;/p&gt;
&lt;p&gt;There&#39;s quite a common design pattern where a wider screen will show the logo and navigation in a sidebar on the left and then in a narrower screen will show it at the top. I&#39;ve used this myself a few times. Here&#39;s a quick illustration of what I mean:&lt;/p&gt;
&lt;div style=&quot;clear: both;&quot;&gt;
&lt;p&gt;[caption id=&amp;quot;attachment_567&amp;quot; align=&amp;quot;aligncenter&amp;quot; width=&amp;quot;200&amp;quot;]&lt;img class=&quot;wp-image-567 size-full&quot; style=&quot;border: solid 1px #000;&quot; src=&quot;https://chrissmith.xyz/img/2017/03/screen-with-sidebar.png&quot; alt=&quot;screen with sidebar&quot; width=&quot;200&quot; height=&quot;150&quot; /&gt; Wider screen with sidebar[/caption]&lt;/p&gt;
&lt;p&gt;[caption id=&amp;quot;attachment_566&amp;quot; align=&amp;quot;aligncenter&amp;quot; width=&amp;quot;150&amp;quot;]&lt;img class=&quot;wp-image-566 size-full&quot; style=&quot;border: solid 1px #000;&quot; src=&quot;https://chrissmith.xyz/img/2017/03/screen-with-header.png&quot; alt=&quot;screen with header&quot; width=&quot;150&quot; height=&quot;200&quot; /&gt; Narrower screen with header[/caption]&lt;/p&gt;
&lt;/div&gt;
My own website, chrissmith.xyz, currently uses this pattern. I&#39;m using the WordPress theme twentyfifteen with my own child theme over it. The twentyfifteen theme uses an &amp;lt;aside&amp;gt; element for logo and navigation. When I&#39;ve built my own sites I used the &amp;lt;header&amp;gt; element for this. My feeling was that the content was semantically header information, and that the fact that it appeared on the side on larger screens was not really important. To me &amp;lt;aside&amp;gt; means that the content is supplementary or in addition to the main content whereas &amp;lt;header&amp;gt;, used at the top level, is almost like a fixed part of the page layout template.
&lt;p&gt;Ultimately, it comes down to the content. I&#39;ve used the &amp;lt;aside&amp;gt; on this site in a fairly static, global way, so really it is a header. The theme creators can&#39;t know how the area is going to be used - if it&#39;s global or changes with the context of each page, so I guess it makes sense to keep the door open and use &amp;lt;aside&amp;gt;.&lt;/p&gt;
&lt;h3&gt;Changing Content&lt;/h3&gt;
We don&#39;t necessarily show the same content at different screen sizes. We might show contextual content in the sidebar but on a smaller screen we might choose not to use it. If we change the displayed content with media queries than how can we use semantic sectioning elements correctly? We could have an &amp;lt;aside&amp;gt; and a &amp;lt;header&amp;gt; in our markup but that&#39;s a lot of unused bloat.
&lt;h3&gt;Aria Roles?&lt;/h3&gt;
Maybe we keep the one element but change the aria-role with JavaScript, e.g. &amp;lt;aside aria-role=&quot;banner&quot;&amp;gt;? Or do we go back to a &amp;lt;div&amp;gt; and use aria-roles?
&lt;h3&gt;Replace HTML?&lt;/h3&gt;
We could even switch out the element using JavaScript. Add the other element, append the content to it and then remove the original element. Or just get something different from the server, either by using a cookie or just a parameter in an Ajax request.
&lt;p&gt;The example I&#39;ve given is quite subtle but I can imagine wanting to combine header, sidebar or footer content on smaller screens. How do we handle this and keep it all semantic?&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
</description>
      <pubDate>Thu, 09 Mar 2017 19:10:24 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2017/html-semantics-header-or-sidebar/</guid>
    </item>
    <item>
      <title>Reorganising Data Client Side</title>
      <link>https://chrissmith.xyz/blog/2017/reorganising-data-client-side/</link>
      <description>&lt;p&gt;I just discovered how easy it can be to reorganise data in JavaScript before trying to use it.&lt;/p&gt;
&lt;p&gt;I&#39;ve been working with a third party API so there&#39;s no option to change the structure of the JSON which we receive. The data I had was organised by date, an object with object properties giving a new object for each new date. Something like:&lt;/p&gt;
&lt;pre&gt;{
  &quot;2017-03-01&quot;: {
    &quot;number&quot;: 2
  },
  &quot;2017-03-02&quot;: {
    &quot;number&quot;: 3
  }
}
&lt;/pre&gt;
&lt;p&gt;I wanted to bind this data to a list, iterating through it. I know it can be done with a &amp;quot;for in&amp;quot; loop but I was using Angular and wanted to use ng-repeat to iterate over an array. So, what I really wanted was this:&lt;/p&gt;
&lt;pre&gt;[
  {
    &quot;date&quot;: &quot;2017-03-01&quot;,
    &quot;number&quot;: 2
  },
  {
    &quot;date&quot;: &quot;2017-03-02&quot;,
    &quot;number&quot;: 3
  }
]  
&lt;/pre&gt;
&lt;p&gt;I don&#39;t know why but I&#39;d always assumed that running a function to reformat the data would be a bad idea and would take a lot of time. I converted my data to the desired format. It worked. I then went further and actually broke down several of the original object properties into separate arrays. Each object got had its properties pushed into 7 separate arrays.&lt;/p&gt;
&lt;p&gt;In my case, looking at a small set of data, under 100 objects, each with around 20 properties, it took about half a millisecond. I timed the reformatting function using console.time(). That&#39;s very fast. So fast that it&#39;s a no-brainer to reformat the data and have it as you want it. It seems that iterating over object properties and pushing items into arrays or renaming properties is trivial so it makes sense to format the data as soon as it is received.&lt;/p&gt;
&lt;p&gt;Here&#39;s an example of a reformatting function, which changes a team object with player object properties into a series of arrays:&lt;/p&gt;
&lt;pre&gt;function reformatData(team) {
  var data = {
    playerNames: [],
    appearances: [],
    goals: [],
    assists: [],
    redCards: [],
    yellowCards: []
  };
  for (var player in team) {
    if (team.hasOwnProperty(player)) {
      data.playerNames.push(team[player].name);
      data.appearances.push(team[player].appearances);
      data.goals.push(team[player].goals);
      data.assists.push(team[player].assists);
      data.redCards.push(team[player].cards.red);
      data.yellowCards.push(team[player].cards.yellow);
    }
  }
  return data;
}
&lt;/pre&gt;
&lt;p&gt;The hasOwnProperty() check means that it will only iterate over the objects &lt;em&gt;own&lt;/em&gt; properties, not &lt;em&gt;all&lt;/em&gt; properties including those inherited from the object prototype. It&#39;s safer and keeps it faster.&lt;/p&gt;
</description>
      <pubDate>Wed, 08 Mar 2017 17:50:17 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2017/reorganising-data-client-side/</guid>
    </item>
    <item>
      <title>Measuring Readership</title>
      <link>https://chrissmith.xyz/blog/2017/measuring-readership/</link>
      <description>&lt;p&gt;I&#39;ve been thinking about how we might more accurately determine how many times a blog post is read. Not just loaded in a browser but actually read.&lt;/p&gt;
&lt;p&gt;Firstly, there are different levels of reading.&lt;/p&gt;
&lt;h3&gt;Level 1: Evaluate Source&lt;/h3&gt;
This is just a quick look to see if the post looks worth spending time on. If the page is full of click bait junk then a discerning user might just back out here. If it looks like a decent quality site then the user will hopefully progress to a...
&lt;h3&gt;Level 2: Quick Scan&lt;/h3&gt;
This is reading the post but at high speed and without taking in all the details. The user might skip over any introductory or background content and try to get straight to the meat. When I scan a piece I tend to navigate by subheadings or by reading the first few words of each new paragraph or section.
&lt;h3&gt;Level 3: Full Read&lt;/h3&gt;
This either means the user knows the blog already and trusts its quality or that he/she has the time and interest to read it properly.
&lt;h3&gt;Analysis&lt;/h3&gt;
Using Google Analytics and filtering we can establish the type of visit rather than it just being a page load.
&lt;p&gt;First up, try to filter out any bots, spiders or non human visitors. When you set up a view Analytics has a nice checkbox option for this.&lt;/p&gt;
&lt;p&gt;The next step is to break the visits down into the levels described above by looking at the length of time on the page. It&#39;s not quite a simple as setting fixed ranges as blog posts will vary in length, so what might be a full read for a short piece could be a scan for a longer one. So, we need to use the word count and the time on page to calculate the level. This means we need 3 ranges of reading speeds which reflect our 3 levels.&lt;/p&gt;
&lt;p&gt;Setting the reading speed levels is largely guess work but I&#39;ve tried to apply some logic to it. Some &lt;a href=&quot;https://www.staples.com/sbd/cre/marketing/technology-research-centers/ereaders/speed-reader/&quot; target=&quot;_blank&quot;&gt;reading speed research&lt;/a&gt; shows that the average reading speed for an adult is around 300 words per minute. That&#39;s five words per second. So, if we get the word count and divide by 5 we&#39;ve got the rough amount of time in seconds that an adult should need to be on the page to read the whole article.&lt;/p&gt;
&lt;p&gt;So, if the seconds spent on the page is greater than or equal to a fifth of the word count then we have level 3, the full read.&lt;/p&gt;
&lt;p&gt;At the other end of the spectrum, what can we discount as an evaluation or bounce? How long can you be on a page before it&#39;s considered that you might be scanning its content? I feel this can be a fixed value rather than relative to the word count as our initial evaluation is done very quickly. Unscientifically, this part is really just plucking a number out of the air but my gut feel is for something like 10 seconds. That&#39;s taking in 50 words. Below that I find it hard to consider that any content has really been processed. I can&#39;t think of a good way to test this out but I may canvas opinion to refine the figure.&lt;/p&gt;
&lt;p&gt;So, we have a page visit time of less than 10 seconds as our level 1 evaluation. That leaves anything in between as level 2, the scan.&lt;/p&gt;
&lt;h3&gt;Fine Tuning&lt;/h3&gt;
Of course users could spend time on the page without necessarily reading anything. We can add some other details to increase the accuracy. Using JavaScript we can listen for a scroll event or better see if the end of the post is shown in the viewport and then send this as a dimension. A lack of scrolling or content visibility would certainly help to qualify the evaluation visits.
&lt;h3&gt;Ideas?&lt;/h3&gt;
Please comment if you think of any further refinements or see any flaws in the logic. Thanks.
</description>
      <pubDate>Sun, 05 Mar 2017 11:15:12 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2017/measuring-readership/</guid>
    </item>
    <item>
      <title>Talking to Machines</title>
      <link>https://chrissmith.xyz/blog/2017/talking-to-machines/</link>
      <description>&lt;p&gt;&amp;quot;Hey Siri&amp;quot;, &amp;quot;OK Google&amp;quot;, &amp;quot;Hey Cortana&amp;quot;. It still feels weird to me.&lt;/p&gt;
&lt;p&gt;As I&#39;m a Windows user Cortana is my &amp;quot;virtual assistant&amp;quot; of choice. It&#39;s an incredibly useful service and getting better all the time so I wonder why I don&#39;t use it more. I&#39;m learning slowly. For example, I just wanted to work out 500 divided by 52. In the past I would have opened the calculator programme or app, typed in my request and got my answer. Today, however, I just said this: &amp;quot;Hey Cortana, what&#39;s five hundred divided by fifty-two.&amp;quot; And, about a second later I had my answer. Much faster.&lt;/p&gt;
&lt;p&gt;I caught myself saying, &amp;quot;thank you&amp;quot;, and immediately felt like an idiot. But actually, that&#39;s not shameful at all, just polite. So what if it was redundant. I&#39;m still human.&lt;/p&gt;
&lt;p&gt;I think there are 2 main reasons why I don&#39;t use it more. Firstly, I just don&#39;t think of it. I&#39;m a bit set in my ways and am too used to typing. Secondly, I&#39;m self-conscious about using it within earshot of other people. It still feels a bit weird, talking to your computer, and I imagine others who can&#39;t hear clearly enough to make out my words wondering who I&#39;m talking to. So, I tend to only use Cortana when I&#39;m on my own, which is even weirder, right? Though, as I never see or hear anyone else using these assistant services I&#39;m guessing I&#39;m probably not alone in this.&lt;/p&gt;
&lt;p&gt;I&#39;m going to try to push through the weirdness and make it more normal in my circles.&lt;/p&gt;
&lt;p&gt;Just for fun, if you&#39;re using Cortana, say this: &amp;quot;Hey Cortana, what does the fox say?&amp;quot; Do it a few times - you&#39;ll get a variety of answers. I guess it probably works on the other assistants too.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
</description>
      <pubDate>Fri, 10 Feb 2017 18:00:39 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2017/talking-to-machines/</guid>
    </item>
    <item>
      <title>Learning the Right Things</title>
      <link>https://chrissmith.xyz/blog/2017/learning-the-right-things/</link>
      <description>&lt;p&gt;With so much happening so fast knowing what new tech to learn next can be difficult. Where should you invest your time and energy? What if you spend ages learning the shiny new framework and it&#39;s gone within 2 years?&lt;/p&gt;
&lt;p&gt;There are a lot of trends and a lot of new-fangled things do come and go. How do you spot the ones that are going to stick around. It&#39;s not easy - you kind of have to go with the flow, not swim against the tide (2 water based metaphors in one sentence, tut).&lt;/p&gt;
&lt;p&gt;In front end development there are currently a few big JavaScript frameworks - Angular, React and Vue. It seems obvious to me that none of these are going away any time soon. Which do you choose? It really doesn&#39;t matter. Learning one in depth, finding its powers and limitations, will help you learn the others or other future technologies.&lt;/p&gt;
&lt;p&gt;If you&#39;re really not sure where to turn I&#39;d focus on core learning. In the front-end world, learn plain JavaScript. With ES2015 and newer versions than that emerging there&#39;s still plenty to take on and perfect. That knowledge will always be useful.&lt;/p&gt;
&lt;p&gt;I guess my short answer would be to favour the evergreen HTML, CSS and JavaScript over associated tech like Pug, Sass, TypeScript, etc. As the core technologies get better over time these current convenience technologies may one day not be needed.&lt;/p&gt;
&lt;p&gt;One word answer. JavaScript. :)&lt;/p&gt;
</description>
      <pubDate>Thu, 09 Feb 2017 18:30:00 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2017/learning-the-right-things/</guid>
    </item>
    <item>
      <title>International box-sizing Awareness Day</title>
      <link>https://chrissmith.xyz/blog/2017/international-box-sizing-awareness-day/</link>
      <description>&lt;p&gt;Today, 1st Feb, is International box-sizing Awareness Day, apparently. Add it to your calendar now! :) I&#39;m not sure how official that is, or who decided it but it&#39;s good to have an annual reminder on some things.&lt;/p&gt;
&lt;p&gt;The general consensus in early 2017 seems to be that the boffins got the spec wrong on this one and border-box should have been the default, so the first line in a lot of stylesheets or pre-processor files is * { box-sizing: border-box; }. The spec can&#39;t change as it would break legacy pages&#39; layout so we&#39;re stuck with this fix.&lt;/p&gt;
&lt;p&gt;That&#39;s fine, and I don&#39;t believe that using the universal selector * causes any real performance issues. Browsers are fast enough and smart enough to take it in their stride. However, I do hit problems with this reset approach. Frameworks.&lt;/p&gt;
&lt;h3&gt;CSS Frameworks&lt;/h3&gt;
I&#39;ve recently tried moving a site which just uses custom CSS and a reset over to Bootstrap 3. Bootstrap uses box-sizing:content-box by default so you chuck in that universal selector and all hell breaks loose. I think that to work with a framework like Bootstrap you have to respect the content-box option and just apply border-box to any custom modules that need it. Basically, if you&#39;re using the framework, use the framework, don&#39;t half use it.
&lt;h3&gt;Table Cells&lt;/h3&gt;
It&#39;s worth noting how table cells behave. They basically have box-sizing border-box by default so padding gets applied inwards. A border between 2 cells gets centered across the cells, so if we have 2 cells with a border of width 10px between them, 5px is effectively within each cell&#39;s width.
&lt;p&gt;You can change the box-sizing property on a cell to content-box but, in short, don&#39;t. It&#39;s not clear how this should behave and is inconsistent across browsers.&lt;/p&gt;
</description>
      <pubDate>Wed, 01 Feb 2017 08:00:41 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2017/international-box-sizing-awareness-day/</guid>
    </item>
    <item>
      <title>iOS vs Android vs Windows in 2017</title>
      <link>https://chrissmith.xyz/blog/2017/ios-vs-android-vs-windows-in-2017/</link>
      <description>&lt;p&gt;Everyone has their favourite big web company and associated operating system (OS). We&#39;re all either Apple, Google or Microsoft. Maybe not quite all of us. There&#39;s always one weirdo who finds something &amp;quot;better&amp;quot;.&lt;/p&gt;
&lt;p&gt;I&#39;d say that for office desk based work most people are either on Apple or Windows (Mac or PC). I&#39;m not sure if any significant numbers use a Chromebook and Chrome as their serious OS. I may be wrong. For phones it&#39;s iOS, Android or, to a lesser extent, Windows. Do people still use Blackberry in big numbers? I&#39;m assuming not.&lt;/p&gt;
&lt;p&gt;People who use Windows for work might have any kind of phone. It&#39;s actually pretty unlikely that they&#39;d have a Windows phone as it&#39;s smaller in the phone market. On the other hand, I bet almost everyone who uses a Mac has an iPhone. And without even considering any of the other options.&lt;/p&gt;
&lt;p&gt;I&#39;m in quite a lucky position where I work on a Windows laptop, use an Android TV box and an iPad at home so have access to all 3 operating systems. I thought I&#39;d do a quick comparison, nothing scientific, or even particularly fair, just my own impressions. I should also point ut that this isn&#39;t about bashing anything. I think all 3 are great. More or less they all do the same things. It&#39;s the little differences and the UX of them that becomes interesting. Here are some pros and cons for each.&lt;/p&gt;
&lt;ul&gt;
 	&lt;li&gt;iOS and Android are miles ahead of Windows in terms of apps available.&lt;/li&gt;
 	&lt;li&gt;iOS is on Apple hardware only whereas you have more choice with Android and Windows.&lt;/li&gt;
 	&lt;li&gt;The point of entry in terms of price is much higher for iOS.&lt;/li&gt;
 	&lt;li&gt;Android (Material) and Windows have more modern UI whereas iOS doesn&#39;t seem to have changed very much in the last few years. Not necessarily a bad thing, just an observation.&lt;/li&gt;
 	&lt;li&gt;iOS has Safari as its default browser, which is not quite as feature rich as Chrome or Edge. It&#39;s easy to install Chrome though.&lt;/li&gt;
&lt;/ul&gt;
For what it&#39;s worth, I have a Windows 10 phone (Microsoft Lumia 550) and I absolutely love it. The main drawback is the lack of apps compared with the other platforms but I don&#39;t find that to be a major obstacle. Since Windows 10 there&#39;s now a first class web browser in Edge so most services which don&#39;t have a Windows app seem to have a web equivalent.
&lt;p&gt;My phone cost me £55 (about $70) and does everything I need, whereas a new iPhone would probably cost me about 10 times that. My phone doesn&#39;t have a great camera or loads of storage, as you&#39;d expect at that low price but I have a digital SLR camera for that. I&#39;m not going to pretend my Windows phone is anywhere near as good in spec compared to the latest iPhone or but I&#39;m also not convinced that my overall mobile experience is 10 times worse. I feel I&#39;m getting the better deal.&lt;/p&gt;
</description>
      <pubDate>Sun, 29 Jan 2017 15:00:57 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2017/ios-vs-android-vs-windows-in-2017/</guid>
    </item>
    <item>
      <title>Opera Neon - First Impressions</title>
      <link>https://chrissmith.xyz/blog/2017/opera-neon-first-impressions/</link>
      <description>&lt;p&gt;&lt;a href=&quot;https://www.opera.com/computer/neon&quot; target=&quot;_blank&quot;&gt;Opera Neon&lt;/a&gt; is the new concept browser from Opera. What&#39;s a &amp;quot;concept browser&amp;quot;? I&#39;ve no idea but I like new shiny things to play with so have been playing. The &lt;a href=&quot;https://www.opera.com/computer/neon&quot; target=&quot;_blank&quot;&gt;Opera Neon webpage&lt;/a&gt; will explain it much better than I can but here are a few first impressions.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://chrissmith.xyz/img/2017/01/opera-neon.png&quot;&gt;&lt;img class=&quot;alignleft size-large wp-image-494&quot; src=&quot;https://chrissmith.xyz/img/2017/01/opera-neon-1024x576.png&quot; alt=&quot;Opera Neon screenshot&quot; width=&quot;660&quot; height=&quot;371&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It uses your desktop background as its background. Very clever. All it&#39;s really doing is copying an image but it changes the whole feel. Rather than looking at a start screen with a white background you&#39;re in a familiar environment of your own choosing.&lt;/p&gt;
&lt;p&gt;The search bar is for keywords or a URL, which is pretty standard, and the way it&#39;s presented is nice and minimal with just an underline yet obvious.&lt;/p&gt;
&lt;p&gt;For your favourite or most recent sites it uses circles with icons rather than screen thumbnails. This makes it feel more like an app start screen, which is quite nice, but I&#39;d probably prefer it to be clearer that they&#39;re shortcuts for the websites. There&#39;s no URL displayed in a tooltip or taskbar when you hover them, which I always like to see as confirmation of where I&#39;m navigating. Maybe I&#39;ve just got that switched off somewhere?&lt;/p&gt;
&lt;p&gt;The layout is very interesting. Open tabs are shown down the right hand side as icons. Key actions and areas like open a new tab or show downloads are shown down the left hand side. It&#39;s almost like a typical mobile or tablet view but rotated 90 degrees. This is refreshing and makes a lot of sense. Most websites viewed on a large desktop screen have content within a central column and there&#39;s a load of margin on either side, wasted space. By using these areas for the browser it retains the full height meaning we get to see more content on screen. Big thumbs up from me.&lt;/p&gt;
&lt;p&gt;Opera Neon has a built-in snap tool for taking and storing screenshots. It&#39;s a camera icon and a gallery icon. Very easy.&lt;/p&gt;
&lt;p&gt;There&#39;s a media player built-in too, so you can listen to music as you browse, which is a neat feature.&lt;/p&gt;
&lt;p&gt;The page title seems to be repeated. There&#39;s one at the very top of the chrome but another internal one at the top of the open tab. As these always seem to be the same it feels a bit redundant.&lt;/p&gt;
&lt;p&gt;It has dev tools. As it&#39;s blink under the hood these are the same as in Chrome though possibly not quite as fully featured to begin with.&lt;/p&gt;
&lt;p&gt;All in all, I&#39;m very impressed. It&#39;ll be interesting to see if it gains market share.&lt;/p&gt;
&lt;p&gt;Just for future reference, I&#39;ve been looking at version 1.0.2459.0.&lt;/p&gt;
</description>
      <pubDate>Sat, 28 Jan 2017 10:00:33 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2017/opera-neon-first-impressions/</guid>
    </item>
    <item>
      <title>Snark Overflow</title>
      <link>https://chrissmith.xyz/blog/2017/snark-overflow/</link>
      <description>&lt;p&gt;&lt;a href=&quot;https://stackoverflow.com/&quot; target=&quot;_blank&quot;&gt;Stack Overflow&lt;/a&gt; is both brilliant and terrible. As a web developer it&#39;s one of those sites that you just have to use, like Can I Use, MDN or CSS Tricks. You can Google any coding issue and the question will pop up in the first few results, you click through, scroll down to the accepted answer or the one with all the upvotes and 8 times out of 10 problem solved. Brilliant.&lt;/p&gt;
&lt;p&gt;There&#39;s another side to it. The accepted answer is selected by the user who asked the question (the OP), someone who isn&#39;t an expert in this area. The solution works, they mark it as the accepted answer and get on with their lives. Meanwhile, others are providing different, possibly better, answers. These better answers may get some upvotes but a lot of visitors are just looking for a quick fix and won&#39;t read every answer and so won&#39;t upvote alternatives in any great numbers. So, the best answer can easily be overlooked.&lt;/p&gt;
&lt;p&gt;There&#39;s also a bandwagon or snowball effect. As more people come past and use the &amp;quot;top&amp;quot; answer it gets more love, pushing other answers further into obscurity.&lt;/p&gt;
&lt;p&gt;Then, there&#39;s another side to it. Time. On the web, things change. What was a great answer 5 years ago might be not be the best way of doing things today. So, you arrive at the question, see the accepted answer and answers with loads of votes and assume they must be right. Maybe not. It only means that they were the most popular answers at some point in time. There could be a much better answer lurking at the bottom with no votes. They need to consider recency as a factor in ranking answers like Google do. Nobody cares about an answer on browsers from 6 years ago.&lt;/p&gt;
&lt;p&gt;Surely you can just ask the question again, a few years later? Oh no! &amp;quot;Duplicate question, duplicate question!&amp;quot; the moderators squeal and it gets binned. It&#39;s happened to me loads of times. &amp;quot;Possible duplicate of question 1917543&amp;quot; they sneer, pointing.&lt;/p&gt;
&lt;p&gt;This, for me is the terrible side. It&#39;s not the flawed logic of the question and answer format, it&#39;s the snarky, show-off, know-it-alls who comment on each other&#39;s answers. Each of them is desperate to show off his or her (his, let&#39;s be honest) own knowledge and score points. Worthless, meaningless points.&lt;/p&gt;
&lt;p&gt;It takes a lot of confidence to submit an answer, raising your head above the parapet, ready to be shot down. It makes me very reluctant to help my fellow developers, which I feel is a sad thing.&lt;/p&gt;
&lt;p&gt;Rant over. I still use it daily so it must be doing something right. :)&lt;/p&gt;
</description>
      <pubDate>Fri, 27 Jan 2017 18:20:49 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2017/snark-overflow/</guid>
    </item>
    <item>
      <title>Blogging Nostalgia</title>
      <link>https://chrissmith.xyz/blog/2017/blogging-nostalgia/</link>
      <description>&lt;p&gt;I started blogging on WordPress back in the summer of 2008. I managed to keep it going through until January 2011, which is quite an achievement in itself. Then, for whatever reason (laziness) it just kind of fizzled out. This was all on my previous site, chris-smith-web.com. I was struggling for a domain name. Can you tell? Don&#39;t bother visiting - it just redirects back here these days.&lt;/p&gt;
&lt;p&gt;I started up again on this site, chrissmith.xyz, in late 2014 and am still going in January 2017. Go me!&lt;/p&gt;
&lt;h3&gt;When 2 Become 1&lt;/h3&gt;
You&#39;ve guessed where this is going. I recently had the idea of closing down the old site and importing all the blog posts into this site. Everything in the one place, less maintenance. Easy win. And surprisingly easy to do. Good job, WordPress! When I publish this post it will be my 89th in all. Zoiks! Let&#39;s try to hit the ton.
&lt;h3&gt;When I Were a Lad&lt;/h3&gt;
I&#39;ve found it fascinating looking back at some of the things I wrote about in the early days. Cue harp music and wobbly faces. It goes to show how fast things move. Here are some of the topics I covered:
&lt;p&gt;&lt;a href=&quot;https://chrissmith.xyz/blog/the-web-20-concept-the-basics/&quot; target=&quot;_blank&quot;&gt;Web 2.0&lt;/a&gt; - what version are we on now? (Aug 2008)&lt;/p&gt;
&lt;blockquote&gt;In the past websites were a one-way read only process, an online brochure which people visited to get information. Now, with the whole concept of Web 2.0, it’s all a two-way interactive process with customers or fans playing an active part in a website.&lt;/blockquote&gt;
Gold.
&lt;hr /&gt;
&lt;p&gt;&lt;a href=&quot;https://chrissmith.xyz/blog/google-chrome-first-impressions/&quot; target=&quot;_blank&quot;&gt;Chrome&lt;/a&gt;, when it was Google Chrome and still in BETA (Sep 2008)&lt;/p&gt;
&lt;blockquote&gt;Having another browser on the scene, and with a big name like &lt;a href=&quot;https://www.google.co.uk/&quot; target=&quot;_blank&quot;&gt;Google&lt;/a&gt; behind it you know it’s going to have a lot of users, means more testing and increases my chances of having to recode.&lt;/blockquote&gt;
Hmm. Didn&#39;t imagine it would be quite so good.
&lt;hr /&gt;
&lt;p&gt;&lt;a href=&quot;https://chrissmith.xyz/blog/links-link-exchanges-and-strategies/&quot; target=&quot;_blank&quot;&gt;Link exchanges&lt;/a&gt;, when that was a thing (Sep 2008)&lt;/p&gt;
&lt;blockquote&gt;Don’t listen to anyone, not even me.&lt;/blockquote&gt;
Excellent advice.
&lt;hr /&gt;
&lt;p&gt;&lt;a href=&quot;https://chrissmith.xyz/blog/web-design-for-different-screen-sizes/&quot; target=&quot;_blank&quot;&gt;Responsive design&lt;/a&gt;, kind of, whatever, I&#39;m claiming it (Sep 2008)&lt;/p&gt;
&lt;blockquote&gt;The majority of users in the UK use a Windows PC with Internet Explorer 7 and a screen resolution of 1024×768 pixels.&lt;/blockquote&gt;
Ouch.
&lt;hr /&gt;
&lt;p&gt;Although a lot has changed there&#39;s actually a lot of good stuff in there that still holds true. I&#39;m quite impressed. Now I just need to get some other people to read it.&lt;/p&gt;
</description>
      <pubDate>Wed, 18 Jan 2017 18:00:37 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2017/blogging-nostalgia/</guid>
    </item>
    <item>
      <title>The End of the EU Cookie Law</title>
      <link>https://chrissmith.xyz/blog/2017/the-end-of-the-eu-cookie-law/</link>
      <description>&lt;p&gt;I don&#39;t want to mislead anyone - I don&#39;t think the law itself is going anywhere but Britain leaving the EU means that the day when I don&#39;t have to worry about it is getting closer.&lt;/p&gt;
&lt;p&gt;There. An actual upside to Brexit.&lt;/p&gt;
&lt;p&gt;I&#39;ve found the whole cookie law to be ridiculous from day one. The US hasn&#39;t felt the need for it. In fact, nowhere else in the world has felt the need for it.&lt;/p&gt;
&lt;p&gt;The basic idea is that a website needs a user&#39;s consent before placing a file (a cookie) on his/her device. That seems fair enough but forcing the publisher to add an annoying message that will always, 100% of the time, be dismissed without any thought is just wasting everybody&#39;s time.&lt;/p&gt;
&lt;p&gt;How can this consent even constitute any kind of legally binding contract when the website visitor is anonymous? And what if he/she is coming from outside the EU?&lt;/p&gt;
&lt;p&gt;Why can&#39;t it be handled by the browser, in a similar way to a website seeking permission to access the user&#39;s location? I&#39;ll tell you why. It&#39;s because the browser vendors don&#39;t consider it an issue. Because it&#39;s not an issue.&lt;/p&gt;
&lt;p&gt;I&#39;m looking forward to the day when I can visit a site without having to dismiss a meaningless message, tick a box or, on the other side of the fence have to add this nonsense and annoy others.&lt;/p&gt;
</description>
      <pubDate>Sun, 15 Jan 2017 13:11:14 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2017/the-end-of-the-eu-cookie-law/</guid>
    </item>
    <item>
      <title>Cut the Crap!</title>
      <link>https://chrissmith.xyz/blog/2017/cut-the-crap/</link>
      <description>&lt;p&gt;We all write loads of crap. All of us. Every day. It&#39;s time to stop. Think it through and cut it out.&lt;/p&gt;
&lt;p&gt;I&#39;m not so much talking about what we say but more the way we say it. We use stupidly over-complicated, flowery, pompous language to express very simple ideas. We should all just keep it clear and simple. The &lt;a href=&quot;https://www.plainenglish.co.uk/&quot; target=&quot;_blank&quot;&gt;Campaign for Plain English&lt;/a&gt; has loads of great examples of ways we can replace the fancy words with simple ones. A few examples:&lt;/p&gt;
&lt;ul&gt;
 	&lt;li&gt;adjacent &lt;i class=&quot;fa fa-arrow-right&quot;&gt;&lt;/i&gt; next to&lt;/li&gt;
 	&lt;li&gt;amendment &lt;i class=&quot;fa fa-arrow-right&quot;&gt;&lt;/i&gt; change&lt;/li&gt;
 	&lt;li&gt;comprises &lt;i class=&quot;fa fa-arrow-right&quot;&gt;&lt;/i&gt; includes&lt;/li&gt;
 	&lt;li&gt;demonstrate &lt;i class=&quot;fa fa-arrow-right&quot;&gt;&lt;/i&gt; show&lt;/li&gt;
 	&lt;li&gt;discontinue &lt;i class=&quot;fa fa-arrow-right&quot;&gt;&lt;/i&gt; stop&lt;/li&gt;
&lt;/ul&gt;
Removing the pretentious vocabulary also makes our writing much easier to understand for people who don&#39;t have English as their first language. It&#39;s all positive with no negatives.
&lt;p&gt;Let&#39;s just keep it simple and cut the crap.&lt;/p&gt;
</description>
      <pubDate>Fri, 13 Jan 2017 18:21:58 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2017/cut-the-crap/</guid>
    </item>
    <item>
      <title>What I Learned in 2016 (Part 3)</title>
      <link>https://chrissmith.xyz/blog/2017/what-i-learned-in-2016-part-3/</link>
      <description>&lt;p&gt;This is the third part of a three part blog post on the things I&#39;ve learned over the last year. So far I&#39;ve covered HTML, CSS and a rare (for me) bit of databasey stuff. And now the final part, the JavaScript...&lt;/p&gt;
&lt;h3&gt;Node.js&lt;/h3&gt;
I haven&#39;t gone into this in depth but was curious about how JavaScript might look on the server. There are lots of in-built functions for working with files and requests but otherwise it really is just JavaScript - objects, functions, if statements, for loops, etc. I think it would take a bit of getting used to but having a JavaScript background it&#39;s probably much easier than learning something else like Ruby or PHP. I learned this from CodeSchool, &lt;a href=&quot;https://www.codeschool.com/courses/real-time-web-with-node-js&quot; target=&quot;_blank&quot;&gt;Real-time Web with Node.js&lt;/a&gt;.
&lt;h3&gt;Modular Functions in JavaScript&lt;/h3&gt;
I really didn&#39;t know what to call this but I know what I mean by it so I&#39;ll try to explain. It&#39;s just a way of thinking about JavaScript functions so they&#39;re separated and easier to test. Each function performs a single job so rather than a function being a wrapper for lots of different jobs, e.g. a conditional test then some string manipulation then constructing an object to return. Each job is broken down into its own function so we end up with lots of tiny functions which call each other rather than long routines. The second part to this is not relying on any variables which sit outside of the function scope. So, not referring back to a variable in the global scope or in a parent function. If our function needs to refer to something it needs to be passed in explicitly as an argument. This just makes it completely self-contained so it can be picked up and dropped in a different context and still do its job without worrying about being affected by the scope.
&lt;p&gt;I started using this methodology after reading a blog post but, sadly, I can not longer remember the source. If anyone knows what this is called or who might have written a good article on it please let em know in the comments.&lt;/p&gt;
&lt;h3&gt;ES2015&lt;/h3&gt;
As I&#39;ve managed to start dropping support for older browsers it has opened the doors on some new features in JavaScript, namely, ES6 or, as I think we&#39;re supposed to call it, ES2015. I did another CodeSchool course, &lt;a href=&quot;https://www.codeschool.com/courses/es2015-the-shape-of-javascript-to-come&quot; target=&quot;_blank&quot;&gt;ES2015: The Shape of JavaScript to Come&lt;/a&gt;. In short it takes a bit of getting used to but ultimately means you can do more writing less, which has to be a good thing. Using tools like &lt;a href=&quot;https://babeljs.io/&quot; target=&quot;_blank&quot;&gt;Babel&lt;/a&gt; we can even use it in older browsers now - it cleverly converts it back to ES5 where needed.
&lt;h3&gt;TypeScript&lt;/h3&gt;
&lt;a href=&quot;https://www.typescriptlang.org/&quot; target=&quot;_blank&quot;&gt;TypeScript&lt;/a&gt; is like JavaScript but upgraded to be a strongly typed object oriented language. It then compiles down to JavaScript, a bit like Sass to CSS. Like CSS is valid Sass, JavaScript is valid TypeScript so you can convert your existing files without it being a major drama. You declare the type of any variable and if there&#39;s any error or uncertainty it won&#39;t compile. This means that you can never have any type errors in production, which is very nice. The number of times I&#39;ve had to fix bugs around some function expecting an integer but getting a string. The other side to it is being able to use modules and classes - it&#39;s proper scoping and namespacing.
&lt;p&gt;As we&#39;re working with Angular I actually did the Pluralsight course, Angular with TypeScript. With hindsight, I&#39;d probably just do a TypeScript course so as not to blur the lines.&lt;/p&gt;
&lt;h3&gt;Dragula&lt;/h3&gt;
This is a library for using drag and drop functionality. I&#39;ve always used &lt;a href=&quot;https://jqueryui.com/droppable/&quot; target=&quot;_blank&quot;&gt;jQuery UI&lt;/a&gt; &lt;a href=&quot;https://jqueryui.com/draggable/&quot; target=&quot;_blank&quot;&gt;draggable&lt;/a&gt;, &lt;a href=&quot;https://jqueryui.com/droppable/&quot; target=&quot;_blank&quot;&gt;droppable&lt;/a&gt; or &lt;a href=&quot;https://jqueryui.com/sortable/&quot; target=&quot;_blank&quot;&gt;sortable&lt;/a&gt; previously but was keen to see what could be done without the jQuery dependency. &lt;a href=&quot;https://bevacqua.github.io/dragula/&quot; target=&quot;_blank&quot;&gt;Dragula&lt;/a&gt; is actually very similar to use, selectors, options object, etc. but uses vanilla JavaScript. Getting into more complex uses the documentation and Stack Overflow answers started to dry up a bit. I guess that&#39;s one of the advantages of using the big libraries.
&lt;h3&gt;Toastr&lt;/h3&gt;
&lt;a href=&quot;https://codeseven.github.io/toastr/&quot; target=&quot;_blank&quot;&gt;Toastr&lt;/a&gt; is another nice little utility library. This does pop-up or toaster notifications. It requires jQuery so may not be for everyone but has loads of options and stacks multiple notifications elegantly, which is not easy. This is probably one of the easiest things I&#39;ve ever used.
&lt;p&gt;And that about wraps it up. Who knows what 2017 holds. At the moment I&#39;m very curious about some new JavaScript frameworks - &lt;a href=&quot;https://vuejs.org/&quot; target=&quot;_blank&quot;&gt;Vue.js&lt;/a&gt; and &lt;a href=&quot;https://svelte.technology/&quot; target=&quot;_blank&quot;&gt;Svelte&lt;/a&gt;.&lt;/p&gt;
</description>
      <pubDate>Sun, 08 Jan 2017 13:00:27 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2017/what-i-learned-in-2016-part-3/</guid>
    </item>
    <item>
      <title>What I Learned in 2016 (Part 2)</title>
      <link>https://chrissmith.xyz/blog/2017/what-i-learned-in-2016-part-2/</link>
      <description>&lt;p&gt;This is the second part of a three-part post about the new things that I picked up through the course of 2016.&lt;/p&gt;
&lt;p&gt;I (finally) took some big steps in CSS this year, picking up some of the things I&#39;d been putting off for a while.&lt;/p&gt;
&lt;h3&gt;Flexbox&lt;/h3&gt;
I&#39;d heard a lot of good things about Flexbox but having to support older browsers I&#39;d never really bothered with it. Finally, this year, with support for older IE getting dropped I decided to dive in. It&#39;s amazing. It can handle just about anything you would need for layouts. I&#39;m sure there are now loads of great resources for learning it but the two I used were Wes Bos&#39;s &lt;a href=&quot;https://flexbox.io/&quot; target=&quot;_blank&quot;&gt;Flexbox.io&lt;/a&gt; videos and Chris Coyier&#39;s &lt;a href=&quot;https://css-tricks.com/snippets/css/a-guide-to-flexbox/&quot; target=&quot;_blank&quot;&gt;A Complete Guide to Flexbox&lt;/a&gt;.
&lt;h3&gt;Sass&lt;/h3&gt;
The really big one for me this year was learning &lt;a href=&quot;https://sass-lang.com/&quot; target=&quot;_blank&quot;&gt;Sass&lt;/a&gt;. I know I&#39;ve come to this very late. I was never that keen on the idea of adding another layer of complexity for my own convenience rather than for any actual user benefit. I still don&#39;t think it&#39;s really needed, it&#39;s a just a nice convenience. That said, it does make writing CSS, particularly modular CSS a lot easier. Nesting, variables and mixins make it much easier to keep things consistent and manageable. CodeSchool&#39;s &lt;a href=&quot;https://www.codeschool.com/courses/assembling-sass&quot; target=&quot;_blank&quot;&gt;Assembling Sass&lt;/a&gt; course was very good.
&lt;h3&gt;Bootstrap&lt;/h3&gt;
I&#39;ve used &lt;a href=&quot;https://getbootstrap.com/&quot; target=&quot;_blank&quot;&gt;Bootstrap&lt;/a&gt; on and off for a while but only recently did a course in it. It turns out that there are loads of little utility classes built in to handle all sorts of variations of the basic components. It&#39;s well worth learning properly rather than just diving in and grabbing bits and pieces. Like with Sass I don&#39;t think you really need a CSS framework but it can certainly speed things along nicely once you know your way around. Our friends at CodeSchool came up trumps again, &lt;a href=&quot;https://www.codeschool.com/courses/blasting-off-with-bootstrap&quot; target=&quot;_blank&quot;&gt;Blasting Off with Bootstrap&lt;/a&gt;.
&lt;h3&gt;(Angular) Material&lt;/h3&gt;
I didn&#39;t go deep into this, just had a bit of a play. &lt;a href=&quot;https://material.angularjs.org/&quot; target=&quot;_blank&quot;&gt;Angular Material&lt;/a&gt; is very nice and fairly easy to use but I came unstuck as I was trying to use parts of the framework within an existing page layout. It got messy pretty quickly. I think Material is a bit &quot;all or nothing&quot; - you use it fully or not at all.
&lt;hr /&gt;
&lt;p&gt;And now for something completely different...&lt;/p&gt;
&lt;p&gt;Being a front-end guy I rarely (never) touch the database world. Writing a request to an API is about as close as I get but recently I&#39;ve poked about with a couple of things.&lt;/p&gt;
&lt;h3&gt;MongoDB&lt;/h3&gt;
I liked the name. I got curious. I&#39;ve done some stuff with SQL many moons ago so I was interested to see how a database could work without it. If you&#39;re used to JavaScript objects and JSON it&#39;s actually really nice to use. You just push and pull objects, query by properties, that kind of thing. I didn&#39;t go deep into it but was very impressed. It&#39;s very much sticking with JavaScript thinking. I think it&#39;s got a bit of a bad reputation but I&#39;m inclined to think that was some early teething trouble and mud sticking rather than a serious issue. Glass half full. I might be wrong.
&lt;h3&gt;Airtable&lt;/h3&gt;
Another play thing. &lt;a href=&quot;https://airtable.com/&quot; target=&quot;_blank&quot;&gt;Airtable&lt;/a&gt; lets you build databases and views, query, filter, sort, run formulae, rollups, lookups, etc. It also gives you forms, galleries where you can show your data in a card format, calendars and a whole lot more. It&#39;s free for the basics and is lovely to use mainly down to some very good UI design. It also has an API for sharing the data with applications.
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;More in the next part...&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
</description>
      <pubDate>Sat, 07 Jan 2017 13:00:16 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2017/what-i-learned-in-2016-part-2/</guid>
    </item>
    <item>
      <title>What I Learned in 2016 (Part 1)</title>
      <link>https://chrissmith.xyz/blog/2017/what-i-learned-in-2016-part-1/</link>
      <description>&lt;p&gt;I&#39;ve done this quick run-through of things I&#39;ve learned in the last 12 months for a few years now. It&#39;s great to reassure myself that I&#39;m still learning and every time it surprises me how much new stuff I&#39;ve picked up in a short space of time.&lt;/p&gt;
&lt;h3&gt;HTML Email&lt;/h3&gt;
For a while I&#39;ve known that you have to use tables and inline styles rather than CSS. Actually there&#39;s a lot more to it and you can use CSS and even media queries. You just have to be prepared for when they&#39;re not supported with nice fallbacks. There&#39;s an excellent course on &lt;a href=&quot;https://www.codeschool.com/&quot; target=&quot;_blank&quot;&gt;CodeSchool&lt;/a&gt; called &lt;a href=&quot;https://www.codeschool.com/courses/unmasking-html-emails&quot; target=&quot;_blank&quot;&gt;Unmasking HTML Emails&lt;/a&gt;.
&lt;h3&gt;SVG&lt;/h3&gt;
I put this one in last year too but I think it&#39;s fair as I&#39;ve learned more this year. It&#39;s surprising how under-used this is considering how easy it is now to make web graphics. I recommend Chris Coyier&#39;s &lt;a href=&quot;https://abookapart.com/products/practical-svg&quot; target=&quot;_blank&quot;&gt;Practical SVG&lt;/a&gt; book.
&lt;h3&gt;Accessibility&lt;/h3&gt;
We all know we should do more but ironically it&#39;s a bit &quot;out of sight, out of mind&quot;. I&#39;ve started to actually do something about it. As I build new screens or components I just run them through some basic checks. There&#39;s a great Chrome extension called &lt;a href=&quot;https://chrome.google.com/webstore/detail/axe/lhdoppojpmngadmnindnejefpokejbdd?utm_source=chrome-app-launcher-info-dialog&quot; target=&quot;_blank&quot;&gt;aXe&lt;/a&gt;, which you run in the dev tools. It lists accessibility violations for your page and even quotes the WCAG docs to show you exactly where you&#39;re causing an issue. It then provides tips on how to resolve the issue, often just adding an aria attribute, title or alt text. I&#39;ve also started checking colours to ensure they have adequate contrast for users with visual impairments but it also just makes it that little bit easier for all users. &lt;a href=&quot;https://contrastchecker.com/&quot; target=&quot;_blank&quot;&gt;Contrast Checker&lt;/a&gt; is a great tool for this and let&#39;s you build up your own palettes and export to PDF.
&lt;h3&gt;Microformats&lt;/h3&gt;
This is an odd one. I&#39;ve stumbled across it and think it&#39;s a really neat idea but I&#39;m not convinced anyone else is using it. Please let me know if you are. It&#39;s basically using a fixed pattern of markup (HTML and classes) to represent a common use case for greater consistency. The example I&#39;ve used is marking up an address with lines for street address, town, county, postcode/ZIP, etc. the theory is that if we use a recognisable format then machines, like browsers, can pick them up and use them intelligently. So, if you add your addresses in this prescriptive format then a phone might offer the user the option of adding it to their contact list. Not sure it it&#39;ll be adopted but it takes a lot of the thinking and naming away. The official docs are at &lt;a href=&quot;https://microformats.org/wiki/microformats2&quot; target=&quot;_blank&quot;&gt;microformats2&lt;/a&gt;. From the blog it does sound pretty active.
&lt;h3&gt;Tab Triggers&lt;/h3&gt;
I&#39;m not sure if this is the right name for them but basically being able to type shorthand code and hit the TAB key writes out proper HTML. For example, in Visual Studio or Codepen, the 2 main tools I use, you can type table&amp;gt;tbody&amp;gt;tr*5&amp;gt;td*3 and hit TAB and you get all the HTML for a table with 5 rows and 3 columns. If you type img and hit TAB you get a self closed image tag with the src and alt attributes inserted. It saves loads of time. Probably the best discovery of the year. Is this the right name for them? Let me know if not.
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;More in the next part...&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
</description>
      <pubDate>Fri, 06 Jan 2017 20:00:13 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2017/what-i-learned-in-2016-part-1/</guid>
    </item>
    <item>
      <title>Code Neat Freak</title>
      <link>https://chrissmith.xyz/blog/2016/code-neat-freak/</link>
      <description>&lt;p&gt;With front-end developers we all care what our UI design looks like in the browser. I&#39;ve started to notice that there are 2 distinct types of developer though - those who are solely focused on the outcome and those who care about the code itself.&lt;/p&gt;
&lt;p&gt;If what appears on the screen looks good and a function does what it&#39;s supposed to do then does the code really matter? I&#39;m not sure.&lt;/p&gt;
&lt;p&gt;Personally, I&#39;m a bit OCD about the code. I arrange all of my CSS rules in alphabetical order and set each new JavaScript block apart with line breaks and add lots of comments.&lt;/p&gt;
&lt;p&gt;Once the code is minified, the messy code and the neat freak code come to the same thing so this tidying up effort is only for humans. Should I be worrying about it and doing it manually or should I just be using the IDE&#39;s formatting tools to do all of this for me?&lt;/p&gt;
</description>
      <pubDate>Fri, 16 Dec 2016 17:06:42 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2016/code-neat-freak/</guid>
    </item>
    <item>
      <title>Is UX Design Really a Thing?</title>
      <link>https://chrissmith.xyz/blog/2016/is-ux-design-really-a-thing/</link>
      <description>&lt;p&gt;This might seem an odd question as user experience (UX for short) obviously has become a thing in the last few years. I think the question I&#39;m really asking is this - isn&#39;t UX design just design? The whole UX thing is kind of meaningless. I know, can of worms...&lt;/p&gt;
&lt;p&gt;In any other industry things get designed but they don&#39;t have special titles for designing for the people using the product - that&#39;s obvious. I can&#39;t imagine that a car designer would be called a driver experience designer. The driver having a positive experience is an inherent part of the design process.&lt;/p&gt;
&lt;p&gt;I guess that the area of UX exists to give some separation from purely aesthetic design. It&#39;s about making things easier to use rather than just pretty. I&#39;ve always seen design as being both. You can&#39;t really have one without the other.&lt;/p&gt;
&lt;p&gt;My other UX gripe is that it&#39;s not really a hard skill, not like development work. It&#39;s something that anyone can do. It&#39;s a blend of common sense, empathy, pretending to forget everything you know and a willingness to fight for what&#39;s best for the user not the developer. When trying to come up with the best user experience for, say, a form, I feel the easiest approach is simply to build something, use it a few times, see where the pain points are, develop alternatives, repeat.&lt;/p&gt;
&lt;p&gt;It&#39;s true that with experience you get it right first time more often but you also get that by imitating the big guns - Amazon, Google, Facebook, BBC. These guys know what they&#39;re doing and have usually done the thinking for us.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
</description>
      <pubDate>Wed, 30 Nov 2016 18:30:58 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2016/is-ux-design-really-a-thing/</guid>
    </item>
    <item>
      <title>Displaying Options in a UI</title>
      <link>https://chrissmith.xyz/blog/2016/displaying-options-in-a-ui/</link>
      <description>&lt;p&gt;One of my pet hates in UIs is seeing a drop down list (select tag) in a form with only a single option in it. As a user you have to click it to see the other available options only to find that there are none. This is a clear example of developer convenience being put before user experience.&lt;/p&gt;
&lt;p&gt;I&#39;m sure it seems obvious now I&#39;ve highlighted it but if there&#39;s only one option then there isn&#39;t a choice to be made at all and we don&#39;t need a form input. The code should conditionally show the drop down list only when there is a selection to be made, more than one item.&lt;/p&gt;
&lt;p&gt;Depending on the UI design, we could even take this a step further. Maybe a drop down list isn&#39;t the best choice for selecting between 2 items? A radio button list is probably better as it enables the user to see all of the available options at a glance and make a selection with a single click/touch. We can test the number of options and if it&#39;s below 5 show the options in a radio button list. &amp;lt;ol&amp;gt; might be a better choice than &amp;lt;ul&amp;gt; for the list if the items are in a specific order, e.g. years.&lt;/p&gt;
&lt;p&gt;Another example I see is displaying disabled form controls where the control is never enabled, e.g. a checkbox which is disabled because the user doesn&#39;t have permissions to change it. If it&#39;s not an option, don&#39;t show it. Disabling it is the lazy option, easy for the developer. Hiding it is much better but may involve a change to layout. The UX should always be put first. It&#39;s usually no more difficult, it&#39;s just not considered.&lt;/p&gt;
</description>
      <pubDate>Wed, 23 Nov 2016 18:30:26 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2016/displaying-options-in-a-ui/</guid>
    </item>
    <item>
      <title>Emotional Response</title>
      <link>https://chrissmith.xyz/blog/2016/emotional-response/</link>
      <description>&lt;p&gt;I&#39;ve read some sales and marketing articles about techniques for trying to elicit an emotional response from your audience. The broad idea is that if you can get your audience to bond with you or your idea on an emotional level then this is very strong. The heart is stronger than the head, if you like.&lt;/p&gt;
&lt;p&gt;I hadn&#39;t taken too much notice but after recent world events it strikes me now that maybe there&#39;s something in it. I&#39;m thinking in particular about the &amp;quot;Brexit&amp;quot; referendum and Donald Trump&#39;s election campaign. In both cases the winning parties made very strong statements, probably much stronger than their actual beliefs or intentions. This strength of message created an emotional response in people, either one way or another - love or hate - there&#39;s no doubt it was divisive. Whilst this approach will undoubtedly lose some supporters the division it creates will harden the resolve of those who do follow. They start to feel like a minority being ridiculed by the opposition and it only makes their belief stronger.&lt;/p&gt;
&lt;p&gt;This is also connected with the idea that all press is good press. Trump must have had far more press column inches than Clinton. Maybe as the negative press coverage gets whipped up into a frenzy people start to feel sorry for the &amp;quot;victim&amp;quot;?&lt;/p&gt;
&lt;p&gt;To give a slightly lighter example, on TV shows like X Factor, most viewers generally pick their favourite in the early stages and then continue to support them throughout. I don&#39;t think there are many viewers who vote for a different contestant each week based on merit. If your favourite gets heavy criticism you&#39;re far more likely to vote. These kind of shows will always be won by the one who seems like a nicest person rather than the most talented.&lt;/p&gt;
&lt;p&gt;Maybe there is something in this trying to make an emotional connection early on?&lt;/p&gt;
</description>
      <pubDate>Tue, 22 Nov 2016 18:52:52 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2016/emotional-response/</guid>
    </item>
    <item>
      <title>Let Off the IE9 Leash</title>
      <link>https://chrissmith.xyz/blog/2016/let-off-the-ie9-leash/</link>
      <description>&lt;p&gt;I recently got the news at work that as of midnight on 31st December 2016 we no longer officially have to support IE9. It&#39;s a sorry state of affairs but come midnight on New Year&#39;s Eve I&#39;m sure this will be in the back of my mind and make me celebrate just that little bit more.&lt;/p&gt;
&lt;p&gt;For the last few years I&#39;ve tended to shy away from using any newer browser features in production as trying to polyfill everything for old IE is either impossible, more trouble than it&#39;s worth or hurts performance. Suddenly, it&#39;s like I&#39;ve been let off the leash. I can use it all.&lt;/p&gt;
&lt;p&gt;It&#39;s a strange feeling. I&#39;m a bit overwhelmed by the possibilities. We can use transforms, transitions, animation, the file API, geolocation - the list goes on, and goes on quite long. The difference between IE9 and IE10 is huge. When IE10 came out Microsoft really caught up and, despite everyone making jokes about IE, there really isn&#39;t much to complain about since version 10.&lt;/p&gt;
&lt;p&gt;Now, when I need my fix of cross-browser complications I&#39;ll have to turn to HTML email. That&#39;s still well and truly screwed up.&lt;/p&gt;
</description>
      <pubDate>Fri, 18 Nov 2016 18:03:38 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2016/let-off-the-ie9-leash/</guid>
    </item>
    <item>
      <title>A/A Testing</title>
      <link>https://chrissmith.xyz/blog/2016/aa-testing/</link>
      <description>&lt;p&gt;I&#39;m guessing most people know what A/B Testing is. It&#39;s publishing 2 variations and monitoring the responses. A typical example might be a web page with a sign up call to action. There would be 2 versions of the page and visitors would be directed to one or the other. After a certain number of page views the number of sign-ups would be counted for each version. Version A might have had 4% sign ups whereas version B might have had 7%. Typically, the best performing page is then either used or put up against another version for another iteration of improvements.&lt;/p&gt;
&lt;p&gt;A/A Testing is the control. Visitors are again directed to one of two pages only this time both versions are exactly the same. Let&#39;s call them A1 and A2. Suppose A1 comes in with 5% sign-ups but A2 comes in with only 1%. What does that tell us? It basically tells us not to read too much into the A/B Testing as the differing results were probably just random chance.&lt;/p&gt;
&lt;p&gt;With A/A Testing, as you monitor more and more users the split should get closer to 50/50. It&#39;s a good way of discovering what is a suitably large sample size for your A/B Tests.&lt;/p&gt;
&lt;p&gt;The other problem with A/B Testing is its format. It&#39;s often set up to work like a knockout, winner stays on tournament - A vs. B, B vs. C, C vs. D, etc. This is flawed. If B beats A, then C beats B, C is the winner. But what if A would beat C? It&#39;s quite possible. For it to work all variations need to put pushed out at once so we&#39;re now doing A/B/C/D Testing and this will require a larger sample size.&lt;/p&gt;
&lt;p&gt;Personally, I&#39;m not convinced it&#39;s very scientific in most cases. I think it can work well if you&#39;re Amazon or Google and have the traffic to get meaningful results but most companies using A/B Testing probably fall way short and are more or less flipping a coin to make their UX decisions.&lt;/p&gt;
&lt;p&gt;A/A Testing is a great way of debunking small scale A/B Testing as it proves that random chance plays a significant part in the outcome.&lt;/p&gt;
</description>
      <pubDate>Thu, 17 Nov 2016 18:00:22 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2016/aa-testing/</guid>
    </item>
    <item>
      <title>Click Fear</title>
      <link>https://chrissmith.xyz/blog/2016/click-fear/</link>
      <description>&lt;p&gt;I recently read this excellent article by Jakob Nielsen:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.nngroup.com/articles/computer-skill-levels/&quot; target=&quot;_blank&quot;&gt;The Distribution of Users&#39; Computer Skills: Worse Than You Think&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It highlights just how bad most people are with using software and websites and how we should not judge our users by our own standards and preferences. As I read it I thought to myself that I don&#39;t really know anyone with poor skills - everyone I know is pretty good at this kind of stuff. Later the same day I was proved wrong.&lt;/p&gt;
&lt;p&gt;I got a call from a friend asking for my help on going through a process online. The options provided seemed obvious to me, even over the phone. They described what they wanted to do and then the 2 options on screen. The first was an exact match for their intention; the second something completely different. It made me realise that it&#39;s often not so much a case of not understanding what to do as being afraid to commit to it and wanting that extra reassurance.&lt;/p&gt;
&lt;p&gt;Some people have a fear that once they&#39;ve pressed a button that&#39;s it and there&#39;s no going back and they&#39;re scared that they may make the wrong choice. I&#39;ve noticed that a lot of websites have &amp;quot;call to action&amp;quot; buttons with text like &amp;quot;Sign up&amp;quot; or &amp;quot;Buy now&amp;quot;. For these users with the fear, this could be a red light - they will see that action as a commitment they may not want. Those of us who know, know that this is just to initiate a process rather than to commit to it. It might be prudent to be cautious with actions and reflect more faithfully what will actually happen.&lt;/p&gt;
&lt;p&gt;There shouldn&#39;t be any need for this fear. Anything that can be done can be undone, or changed later. Well, almost anything. I can think of a few instances where choosing a username is a permanent choice but it&#39;s usually made clear if something cannot be changed.&lt;/p&gt;
&lt;p&gt;To use a not-particularly-thought-through analogy, navigating through any kind of process online is a bit like driving around a car park. Whichever route you take you can always loop back around and get back to where you were. Worst case scenario - you can always exit and enter again.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
</description>
      <pubDate>Wed, 16 Nov 2016 18:00:45 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2016/click-fear/</guid>
    </item>
    <item>
      <title>Bad Web Dev</title>
      <link>https://chrissmith.xyz/blog/2016/bad-web-dev/</link>
      <description>&lt;p&gt;Sometimes I see stuff on web pages and wonder how the developers ever thought that was OK…&lt;/p&gt;
&lt;blockquote class=&quot;wp-block-quote&quot;&gt;&lt;p&gt;&lt;strong&gt;&quot;Please make sure you click on this button only once or you may be charged twice.&quot;&lt;/strong&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;We&#39;re server side guys. We don&#39;t really do front end. We don&#39;t know how to disable the button when it&#39;s clicked to prevent this so we&#39;ll just warn you not to click it. Yeah, that&#39;ll be fine.&lt;/p&gt;
&lt;blockquote class=&quot;wp-block-quote&quot;&gt;&lt;p&gt;&lt;strong&gt;&quot;Please contact your system administrator.&quot;&lt;/strong&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Dunno. Your bad, not ours. You figure it out. We&#39;re washing our hands of this whole thing.&lt;/p&gt;
</description>
      <pubDate>Fri, 04 Nov 2016 08:55:06 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2016/bad-web-dev/</guid>
    </item>
    <item>
      <title>When to Hide and When to Disable</title>
      <link>https://chrissmith.xyz/blog/2016/when-to-hide-and-when-to-disable/</link>
      <description>&lt;p&gt;I&#39;ve noticed a bit of a recurring theme in UX work with people asking me whether a page element should be hidden from the user or just disabled.&lt;/p&gt;
&lt;p&gt;To me, it seems quite clear cut. If the user isn&#39;t going to use the element, hide it. If they can&#39;t use it now but may do when conditions are right, disable it.&lt;/p&gt;
&lt;p&gt;A typical example is a form with a Save button. We don&#39;t want users to be able to save until the form is valid, completed as we&#39;ve specified. We could just show and enable the button and then throw validation errors. However, it seems more appropriate to me to simply not make the save option available until it can actually perform its function and save the data. In this case do we hide the button or disable it?&lt;/p&gt;
&lt;p&gt;I&#39;d argue that we disable the Save button. We don&#39;t want it to be used now but we want to communicate the possibility of using it in the future. It&#39;s useful for a user to see what the next step is going to be.&lt;/p&gt;
&lt;p&gt;If we hide the button instead of disabling it then the user is confronted with a form and no obvious action. If they think there&#39;s no way of progressing they may be reluctant to spend their time filling out the form.&lt;/p&gt;
&lt;p&gt;Another example might be a Delete button where only certain user roles have permission to delete records. In this case it makes sense to hide the button from users without delete permissions. They will never use it, at least not with their current role on this page load, so showing it as disabled would give the wrong suggestion that they may be able to delete at some point.&lt;/p&gt;
&lt;h3&gt;Just Hidden or Never There&lt;/h3&gt;
If we decide that an element will never be used by the current user, maybe due to permissions, then we hide it. However, there&#39;s a difference between adding the element into the DOM and hiding it with CSS, like display:none or visibility:hidden and simply not adding it into the DOM. It&#39;s better both for security and from a page performance point of view to not add it into the DOM. Conditionally add the element using server side code or, in a front-end framework, use the option which does not add it. For example, in AngularJS this would mean using ngIf rather than ngShow.
&lt;h3&gt;Disabling Links&lt;/h3&gt;
Another issue that comes up is people wanting to disable links. So, there&#39;s a link to another page but this option only becomes available to use when certain conditions in the page are met. Should this link be hidden or disabled?
&lt;p&gt;This is tougher. By default links don&#39;t have a disabled state in HTML, only form elements. We can make a link element effectively disabled using CSS - making its text grey or lowering the opacity and setting pointer-events:none to prevent any click or hover events.&lt;/p&gt;
&lt;p&gt;I don&#39;t know if it&#39;s just me being a purist but I feel that disabled links are a bad idea. We should be using the established patterns rather than trying to invent new ones to solve problems. If our default enabled links were blue and our disabled ones pale grey, how would a user know this? Unfamiliar with the concept of grey links they would probably assume that it was just a :visited link and still try to use it.&lt;/p&gt;
&lt;p&gt;With links I feel it&#39;s better for them to be simply shown or hidden. If they are revealed when certain conditions are met then it may be useful to add an animation to draw attention to them as they appear.&lt;/p&gt;
</description>
      <pubDate>Fri, 30 Sep 2016 08:24:39 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2016/when-to-hide-and-when-to-disable/</guid>
    </item>
    <item>
      <title>Getting Feedback on Codepen Demos</title>
      <link>https://chrissmith.xyz/blog/2016/getting-feedback-on-codepen-demos/</link>
      <description>&lt;p&gt;At the software company where I work, we&#39;ve started using &lt;a href=&quot;https://codepen.io/&quot; target=&quot;_blank&quot;&gt;Codepen&lt;/a&gt; as a way of producing interactive demos or prototype pages. It&#39;s slowly replacing the use of static images or mock-ups. We&#39;ve started sharing the URLs for these with customers to get their feedback on new features.&lt;/p&gt;
&lt;p&gt;This could be done by sending them 2 URLs, one for the pen and one for the feedback form, but it&#39;s not as good as being able to complete the form whilst viewing the demo content at the same time. I came up with a way of requesting feedback within the pen.&lt;/p&gt;
&lt;h3&gt;SurveyMonkey&lt;/h3&gt;
I embedded a &lt;a href=&quot;https://www.surveymonkey.com/&quot; target=&quot;_blank&quot;&gt;SurveyMonkey&lt;/a&gt; survey tracking script within the pen. I amended the pen design slightly to add a sidebar div and then added the SurveyMonkey embed JavaScript block within this, in the HTML pane of the pen. The script had to be here so that it rendered in the right place. I gave this sidebar a fixed width so that we could control how the survey contents appeared. We then had to write the survey in such a way that it didn&#39;t require much screen width and that all questions would fit into a sensible minimum screen height. In short, we kept questions short, no lists of 10 radio buttons.
&lt;h3&gt;CrazyEgg&lt;/h3&gt;
I decided to also embed &lt;a href=&quot;https://www.crazyegg.com/&quot; target=&quot;_blank&quot;&gt;CrazyEgg&lt;/a&gt;. If you don&#39;t know it, it&#39;s a tool that allows you to track mouse clicks. It&#39;s a very useful way of knowing which parts of your screen get the most interaction. We added this script into the head content, within the HTML settings. This is a paid service but you can get a free trial for a short time.
&lt;h3&gt;Debug Mode&lt;/h3&gt;
The 2 scripts seemed to get blocked when we tried using the pen in Editor or Full Screen modes but Debug mode, which runs the code as it is without any header or validation, worked like a dream. You need a PRO account to use this mode. Well worth it anyway in my view.
&lt;h3&gt;Feedback Ready&lt;/h3&gt;
I&#39;m now looking at building this out as a template ready for future feedback gathering.
</description>
      <pubDate>Sat, 28 May 2016 09:00:45 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2016/getting-feedback-on-codepen-demos/</guid>
    </item>
    <item>
      <title>Beautifying Native Form Elements</title>
      <link>https://chrissmith.xyz/blog/2016/beautifying-native-form-elements/</link>
      <description>&lt;p&gt;The various types of form inputs can look very different in different browsers. When it comes to styling them there&#39;s only so much we can control. Here are all the form elements (at the time of writing) in one pen. Try viewing it in different browsers to see how they appear.&lt;/p&gt;
&lt;p&gt;[codepen_embed height=500 theme_id=1 slug_hash=&#39;pymBWL&#39; user=&#39;chris22smith&#39; default_tab=&#39;result&#39; animations=&#39;run&#39;]
See the Pen &amp;lt;a href=&#39;https://codepen.io/chris22smith/pen/pymBWL&#39;&amp;gt;All Form Elements&amp;lt;/a&amp;gt;.
[/codepen_embed]&lt;/p&gt;
&lt;p&gt;It bugs me that the width and height of these elements seem inconsistent, as do text sizes, shading, etc. It makes it hard to create attractive forms and have everything align nicely.&lt;/p&gt;
&lt;h3&gt;A Style Base (CSS Reset) for Form Elements&lt;/h3&gt;
It&#39;s not too difficult to try to bring some control to the styling. Textareas, inputs which accept text and buttons are basically boxes and we can style them just like div elements. Other inputs can have special features but we can still change the basics - height, width, font-family, font-size, margin, padding, color, border, border-radius.
&lt;p&gt;[codepen_embed height=500 theme_id=1 slug_hash=&#39;PNvvXd&#39; user=&#39;chris22smith&#39; default_tab=&#39;result&#39; animations=&#39;run&#39;]
See the Pen &amp;lt;a href=&#39;https://codepen.io/chris22smith/pen/PNvvXd&#39;&amp;gt;All Form Elements - Style Base&amp;lt;/a&amp;gt;.
[/codepen_embed]&lt;/p&gt;
&lt;p&gt;This light scattering of CSS seems to bring it under control and &amp;quot;flexbox&amp;quot; is a nice way of making everything align and behave responsively.&lt;/p&gt;
&lt;p&gt;I don&#39;t think there&#39;s any hope for keygen but, to be honest, I&#39;d never even heard of it before starting this so I&#39;m not going to lose any sleep.&lt;/p&gt;
&lt;p&gt;Please fork either of these pens and try out your own form styling.&lt;/p&gt;
</description>
      <pubDate>Fri, 27 May 2016 17:20:20 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2016/beautifying-native-form-elements/</guid>
    </item>
    <item>
      <title>Star Wars Mini Projects in Codepen</title>
      <link>https://chrissmith.xyz/blog/2016/star-wars-mini-projects-in-codepen/</link>
      <description>&lt;p&gt;The Star Wars universe seems to be a bit of a recurring theme for me when experimenting with 3D modelling and animation in Codepen. Here are some pens and a bit of explanation of how they were made. Naturally the code is available by switching the view.&lt;/p&gt;
&lt;h3&gt;CSS 3D Tie Fighter Wireframe&lt;/h3&gt;
[codepen_embed height=500 theme_id=1 slug_hash=&#39;wMYaBL&#39; user=&#39;chris22smith&#39; default_tab=&#39;result&#39; animations=&#39;run&#39;]
See the Pen &amp;lt;a href=&#39;https://codepen.io/chris22smith/pen/wMYaBL&#39;&amp;gt;CSS 3D Tie Fighter Wireframe&amp;lt;/a&amp;gt;.
[/codepen_embed]
&lt;p&gt;The Tie Fighter body is just made up of a number of circles, &amp;lt;div&amp;gt;s with border-radius:50% rotated using transform:rotateY(). See the pen &lt;a href=&quot;https://codepen.io/chris22smith/pen/LGeVzz&quot; target=&quot;_blank&quot;&gt;CSS Sphere Wireframe&lt;/a&gt; to see this part in isolation. The front cockpit window circles are the same but brought forward using transform:translateZ(). The axle is actually just 2 flat rectangles. One is brought slightly forwards and the other is set slightly back using transform:translateZ(). The hexagonal wings were the most difficult part. The hexagons are made up of 3 rectangles rotated through 60 degrees. The inner triangles are then formed using pseudo elements inside these triangles which are rotated 30 degrees and have one border applied and the dimensions set just right. See the pen &lt;a href=&quot;https://codepen.io/chris22smith/pen/EPeYmL&quot; target=&quot;_blank&quot;&gt;CSS Hexagon with inner triangles&lt;/a&gt; to see just this part. Finally, the whole thing, the .sphere, is rotated to show off the 3D. The blueprint style background is a combination of linear gradients and background sizing and positioning.&lt;/p&gt;
&lt;h3&gt;Tie Fighter Attack&lt;/h3&gt;
[codepen_embed height=500 theme_id=1 slug_hash=&#39;EKKeZv&#39; user=&#39;chris22smith&#39; default_tab=&#39;result&#39; animations=&#39;run&#39;]
See the Pen &amp;lt;a href=&#39;https://codepen.io/chris22smith/pen/EKKeZv&#39;&amp;gt;Tie Fighter Attack&amp;lt;/a&amp;gt;.
[/codepen_embed]
&lt;p&gt;In this project the Tie Fighters are much simpler. Each one is actually just a letter H in a sans-serif font with a small circle (border-radius) over the centre of it. I use JavaScript to set a random position within the viewport, randomly scale and rotate each one slightly so they appear less uniform. The movement is just CSS. Each one uses a keyframe animation to increase it&#39;s Z position using transform:translateZ(). So, it is generated, animated towards the viewer until the perspective means it&#39;s out of sight and then removed from the DOM. I just keep doing this at regular intervals and it gives the appearance of lots of objects moving towards the viewer, just missing. Another effect at play here is the opacity. Each Tie Fighter starts off with 0 opacity and it increases to 1 as they approach giving the appearance of them coming out of a fog becoming clearer as they approach. The final effect is the shooting. A random proportion of the fighters shoot. These are assigned a class and then use a pseudo element to draw a tall thin box below the main fighter. This is invisible but has green box-shadow. This then uses a CSS animation to add a blink effect.&lt;/p&gt;
&lt;h3&gt;3D Death Star&lt;/h3&gt;
[codepen_embed height=500 theme_id=1 slug_hash=&#39;QNYOQQ&#39; user=&#39;chris22smith&#39; default_tab=&#39;result&#39; animations=&#39;run&#39;]
See the Pen &amp;lt;a href=&#39;https://codepen.io/chris22smith/pen/QNYOQQ&#39;&amp;gt;3D Death Star&amp;lt;/a&amp;gt;.
[/codepen_embed]
&lt;p&gt;This project uses a 3D sphere made up of rotated circles which rotates. It has one static circle inside it, which is achieved by rotating it in the opposite direction. This has a linear gradient to give it a three dimensional feel. The indented weapon part is just another circle placed on the surface with the gradient running in the opposite direction. The stars are positioned randomly using JavaScript and appear in 3 layers. These are rotated against the Death Star to give the impression of movement.&lt;/p&gt;
&lt;p&gt;You can find lots of great pens in &lt;a href=&quot;https://codepen.io/mariemosley/&quot;&gt;Marie Mosley&lt;/a&gt;&#39;s &lt;a href=&quot;https://codepen.io/collection/nbGZVv/&quot; target=&quot;_blank&quot;&gt;Star Wars collection&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
</description>
      <pubDate>Wed, 18 May 2016 18:47:28 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2016/star-wars-mini-projects-in-codepen/</guid>
    </item>
    <item>
      <title>Web Animation Tips</title>
      <link>https://chrissmith.xyz/blog/2016/web-animations-tips/</link>
      <description>&lt;p&gt;Here are a few techniques I use in making web animations in &lt;a href=&quot;https://codepen.io/chris22smith&quot; target=&quot;_blank&quot;&gt;Codepen&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Zooming&lt;/h3&gt;
By zooming all I really mean is moving things nearer or further by animating them along the Z axis with transform:translateZ(). This needs to be used in conjunction with the perspective and perspective-origin rules on a parent element. I tend to put this on the html element.
&lt;p&gt;I like to set the opacity at 1 when elements are close up and fade them down to a lower opacity as they&#39;re further away. This gives a very natural feeling of coming into focus or if exaggerated can give the impression of something emerging from a fog.&lt;/p&gt;
&lt;p&gt;Example: &lt;a href=&quot;https://codepen.io/chris22smith/pen/BKaWBd&quot; target=&quot;_blank&quot;&gt;Tie Fighter Waves&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Rotation&lt;/h3&gt;
I quite often use rotation to make 3D objects spin on screen. It would be a shame to go to the trouble of making a 3D object with detail on all sides only to see part of it. Turning it round slowly is an easy way showing it off. Use a keyframe animation for this rotating the object around the Y axis.
&lt;p&gt;@keyframes spin {
0% { transform:rotateY(0deg); }
100% { transform:rotateY(360deg); }
}&lt;/p&gt;
&lt;p&gt;.spin { animation: spin 5s linear infinite; }&lt;/p&gt;
&lt;h3&gt;Shaking&lt;/h3&gt;
Making an object shake is a great way of drawing attention to it or giving the ipression taht something is alive or vibrating like an engine. It&#39;s easy to make objects shake using keyframe animations.
&lt;p&gt;@keyframes shake {
0% { transform:translateX(-2px); }
100% { transform:translateX(2px); }
}&lt;/p&gt;
&lt;p&gt;.shake { animation: shake 100ms linear alternate infinite; }&lt;/p&gt;
</description>
      <pubDate>Mon, 25 Apr 2016 17:54:22 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2016/web-animations-tips/</guid>
    </item>
    <item>
      <title>Mother Nature in Web Design</title>
      <link>https://chrissmith.xyz/blog/2016/mother-nature-in-web-design/</link>
      <description>&lt;p&gt;How can we make designs feel more like the natural world and less like something created on a machine? Here are a few ideas...&lt;/p&gt;
&lt;h3&gt;Randomness&lt;/h3&gt;
I&#39;ve created a few pens on &lt;a href=&quot;https://codepen.io/&quot; target=&quot;_blank&quot;&gt;Codepen&lt;/a&gt; recently which involve JavaScript generating random elements in the DOM. Add a new element and assign it random position, dimensions or scale.
&lt;p&gt;&lt;a href=&quot;https://codepen.io/chris22smith/pen/GoVVPY&quot; target=&quot;_blank&quot;&gt;Furball&lt;/a&gt;
&lt;a href=&quot;https://codepen.io/chris22smith/pen/BKaWBd&quot; target=&quot;_blank&quot;&gt;Tie Fighter Waves&lt;/a&gt;
&lt;a href=&quot;https://codepen.io/chris22smith/pen/WrzVxw&quot; target=&quot;_blank&quot;&gt;Random Circles&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Whilst these were just playing around, I am interested by the idea of bringing an element of randomness into designs. There&#39;s a real feeling of the natural world or at least being outside in allowing things to be created and move around of their own accord or, at least, appear to.&lt;/p&gt;
&lt;h3&gt;Position&lt;/h3&gt;
To do this we can use JavaScript to assign elements a random position. Set position:absolute and then generate random numbers for left and top values within the confines of the viewport width and height.
&lt;h3&gt;Movement&lt;/h3&gt;
In nature things don&#39;t generally move in a linear way. They accelerate, reach their desired speed and then decelerate again before stopping - its not sudden. Similarly, things don&#39;t just appear or disappear but gradually fade in or out of view or move in gradually from outside the range of vision. Things don&#39;t always stay upright. They turn and sway. They&#39;re affected by wind outside.
&lt;p&gt;Keyframe animation with transforms, especially translate and rotate, can help make things move quite subtly giving a very natural feel.&lt;/p&gt;
&lt;h3&gt;Lighting&lt;/h3&gt;
Light is not a constant in nature, except maybe in the dessert. It is affected by cloud cover and so the lightness/darkness of things will vary. Shadows don&#39;t stay fixed for long but may change direction and intensity outside.
</description>
      <pubDate>Sat, 23 Apr 2016 10:16:16 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2016/mother-nature-in-web-design/</guid>
    </item>
    <item>
      <title>Lazy HTML :(</title>
      <link>https://chrissmith.xyz/blog/2016/lazy-html/</link>
      <description>&lt;p&gt;Poking through other developers&#39; HTML pages I sometimes come across markup like this:&lt;/p&gt;
&lt;p&gt;&amp;lt;br&amp;gt;
&amp;lt;br&amp;gt;
&amp;lt;br&amp;gt;&lt;/p&gt;
&lt;p&gt;It&#39;s generally used to just add some space between block elements. My instinctive reaction is a mixture of horror and disbelief. I can&#39;t remove it quick enough and get some CSS to control it instead.&lt;/p&gt;
&lt;p&gt;Thinking about it a little deeper, this tag gets misused a lot. There&#39;s a big difference between a semantic break between 2 bits of content and just shifting something down a line because it looks better at the time. The example above using several line breaks consecutively is, to my mind, just plain wrong. A break is used to separate content and its semantic meaning here is trying to separate other breaks.&lt;/p&gt;
&lt;p&gt;To be fair to the other developers there&#39;s a good chance it&#39;s some visual editor doing a bad job rather than it being hand coded this way but the result is the same.&lt;/p&gt;
&lt;p&gt;HTML should be about conveying the meaning of the content, not just a way of putting text on screen. Adding gaps or breaks between bits of content needs to be considered too.&lt;/p&gt;
&lt;h3&gt;Margin vs Padding&lt;/h3&gt;
We get a similar situation with margin and padding. Some developers just use these interchangeably to put a gap between elements but this feels wrong to me. Even though this is purely styling rather than content and doesn&#39;t need to worry about semantics in the same way, it&#39;s still a matter of how you view a particular element. If it appeared in another context, would it always have this margin or padding? I think we should be designing chunks of content as independent elements, which can be dropped into a page ready to go without the need for excessive styling for their context.
</description>
      <pubDate>Thu, 21 Apr 2016 19:15:08 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2016/lazy-html/</guid>
    </item>
    <item>
      <title>Ordering CSS Properties A-Z</title>
      <link>https://chrissmith.xyz/blog/2016/ordering-css-properties-a-z/</link>
      <description>&lt;p&gt;How do you order your CSS properties? There are a few different possible ways that spring to mind:&lt;/p&gt;
&lt;ol&gt;
 	&lt;li&gt;Sort all properties alphabetically, listing them A-Z&lt;/li&gt;
 	&lt;li&gt;Group properties by their meanings, e.g. typographical properties first, then sizing, then shadows, then animations, etc.&lt;/li&gt;
 	&lt;li&gt;Random - just added as they occur to the developer.&lt;/li&gt;
&lt;/ol&gt;
I started off with them just logged randomly. Then, as I started writing longer style rules, I tried to bring similar items together. Gradually, over a long time, I&#39;ve realised that the point of this grouping was to make the properties easier to find quickly. These days I always list them A-Z.
&lt;h3&gt;Going A-Z&lt;/h3&gt;
At first it seems a bit obsessive-compulsive to order them in this way but it does make a real difference. I think things probably changed for me when I started working with JavaScript objects and JSON and the browser dev tools naturally ordered the object properties alphabetically. I got used to them being listed this way and learnt to scan these lists in a logical way. With CSS I&#39;m convinced that in a list of 10 or more properties that being able to scan them in order and focus on the makes a huge difference when doing it every few minutes.
&lt;h3&gt;CSS Property Naming&lt;/h3&gt;
Using A-Z ordering has made me realise how much of an opportunity has been missed with the property naming. For example, &#39;border-top-right-radius&#39; would have been so much better as &#39;border-radius-top-right&#39; as it would keep all of the &#39;border-radius&#39; properties together in an alphabetical list. Also, some typographical properties being prefixed with &#39;font-&#39; and others &#39;text-&#39; means that they don&#39;t get naturally grouped and &#39;color&#39; seems stranded out on its own. Hopefully, some future incarnation of CSS will allow some aliasing of property names.
&lt;h3&gt;Code Editor Property Sorting&lt;/h3&gt;
I use different code editors for different projects but my main day-to-day one is Visual Studio. The &lt;a href=&quot;https://www.jetbrains.com/resharper/&quot; target=&quot;_blank&quot;&gt;ReSharper&lt;/a&gt; tool, a paid extension, offers some code clean-up options, one of which is to order all CSS properties A-Z. This enables me to go back to code I worked on pre-A-Z and quickly kick it into shape in a couple of clicks. I don&#39;t know of any other tools that do this but I&#39;m sure they must exist, my guess would be as extensions/plugins rather than a core feature.
</description>
      <pubDate>Wed, 20 Apr 2016 21:32:39 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2016/ordering-css-properties-a-z/</guid>
    </item>
    <item>
      <title>What to Look For in a Web Designer or Design Agency</title>
      <link>https://chrissmith.xyz/blog/2016/what-to-look-for-in-a-web-designer-or-design-agency/</link>
      <description>&lt;p&gt;Imagine you&#39;re a business owner or marketing bod and you need to get either a new website or you want a redesign of your current, slightly tired looking site. You need to hire a web designer or design agency. How do you tell the good from the bad?&lt;/p&gt;
&lt;p&gt;Web designers range from the top end agencies who have major international corporations in their portfolios down to someone&#39;s neighbour&#39;s kid who made a website for someone once. Chances are you want something in between - not paying over the odds and not getting something held together by sticky tape.&lt;/p&gt;
&lt;h3&gt;Agency or Freelance Designer&lt;/h3&gt;
I&#39;d say your first choice is knowing whether to go with an individual or an agency. Traditionally agencies would cost you more as they had an office with bills and marketing costs whereas an individual might be working from their room. Today, with more home working, those lines are a bit more blurred and some very good agencies might be made up of remote workers. An agency brings some reassurance, that if a particular person is on holiday for 3 weeks, off ill or leaves then there&#39;s usually someone else to pick up your work, whereas with an individual you might not have that fallback. By the same token, some designers have very sound fallback plans - working with other designers, passing all relevant access back to the client so it can be picked up by another freelancer. It&#39;s really a case of asking the right questions and making sure you feel adequately covered for what you need.
&lt;h3&gt;It&#39;s all about how it looks&lt;/h3&gt;
Look at what the designers have done previously. Obviously consider if the designs look appealing but look slightly beyond that. Is each design tailored to the content of the site or business it represents or are they trotting out the same template for all their sites? An overuse of templates suggests that they&#39;re bashing out sites as quickly as possible for maximum profit rather than really caring about doing a good job.
&lt;h3&gt;Actually, it&#39;s not about how it looks&lt;/h3&gt;
Looks are one thing but how a site performs for you is much more important. It needs to load quickly and display properly on any device. Some sites have great home page animations or big images which cycle to promote things. Whilst these may look great on a desktop they&#39;re a nightmare on a mobile device without WiFi. If a user has to wait 30 seconds for your page to load and then pinch and zoom to read your page, do you think they&#39;ll hurry back? Fast loading and appropriate sizing for all devices is essential.
&lt;p&gt;Ask about page speed and responsive design. If they don&#39;t seem to know about this, or view it as an extra, run, run fast, far away. Responsive design is not a &amp;quot;nice to have&amp;quot; like it was a few years back, it&#39;s critical. Even if you think you&#39;ll never have any mobile visitors, 1) you&#39;re wrong, by the way, and 2) having a site work on mobile is a key factor in Google&#39;s ranking of search results. If it doesn&#39;t perform well on mobile Google&#39;s search ranking algorithm will lock your site in a dungeon and make it eat nothing but porridge for the rest of its anonymous life. Probably.&lt;/p&gt;
&lt;h3&gt;Relationships&lt;/h3&gt;
You also need to consider if you&#39;re looking for a one-off piece of work that&#39;s signed off and shipped or an ongoing relationship where they will keep working on your site. Make sure you find out costs for any future work - new features or pages or tweaks to existing stuff - even if you don&#39;t think you&#39;ll need it. It&#39;ll give you a good idea of how they operate.
&lt;h3&gt;UK VAT&lt;/h3&gt;
This applies to the UK. I&#39;m not sure quite how Value Added Tax or equivalents work in other territories. If you&#39;re a small business, individual, club, etc and not VAT registered yourself it may pay to find a freelance designer who is also not VAT registered as it will save you having to pay an extra 20%. This does imply that they&#39;re working at a lower turnover level but for a smaller project this might be a better fit.
&lt;h3&gt;Summary&lt;/h3&gt;
To bring that all together in a nice to do list, ask about the following:
&lt;ul&gt;
	&lt;li&gt;Fallback plans if the designer is not available&lt;/li&gt;
	&lt;li&gt;Use of templates&lt;/li&gt;
	&lt;li&gt;Page loading times, especially on mobile&lt;/li&gt;
	&lt;li&gt;Appearance on different devices&lt;/li&gt;
	&lt;li&gt;Ongoing or future work&lt;/li&gt;
	&lt;li&gt;Are they VAT registered (if relevant)?&lt;/li&gt;
&lt;/ul&gt;
</description>
      <pubDate>Wed, 06 Apr 2016 17:45:23 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2016/what-to-look-for-in-a-web-designer-or-design-agency/</guid>
    </item>
    <item>
      <title>Can I Track It?</title>
      <link>https://chrissmith.xyz/blog/2016/can-i-track-it/</link>
      <description>&lt;p&gt;I&#39;m not sure what proportion of websites include Google Analytics tracking scripts. I&#39;d be guessing. What I do know is that every site I&#39;ve worked on in the last decade or so has made use of it.&lt;/p&gt;
&lt;p&gt;The part I feel more confident about guessing is that only a very small minority use anything beyond the most basic out of the box usage. This was true of me until only a few months ago when I was asked if we could track something other than a simple page load.&lt;/p&gt;
&lt;h3&gt;Tracking Events&lt;/h3&gt;
It seems like a big thing initially but is actually quite straightforward. You just use any JavaScript event, like a click or change, and send some details to identify it off to Google, all asynchronously. Then it shows up in your reporting. &lt;a href=&quot;https://developers.google.com/analytics/devguides/collection/analyticsjs/events&quot; target=&quot;_blank&quot;&gt;Analytics for Web Event Tracking&lt;/a&gt;
&lt;p&gt;This almost becomes a consideration in everything you do in JavaScript. Every time a user takes any kind of action in the UI ask if it&#39;s worth tracking. It can be incredibly useful for a new site or new feature to understand exactly how things are being used in the wild. I&#39;d say if in doubt, track it, analyse it, then once you know how it works and you&#39;re happy with the result stop tracking.&lt;/p&gt;
</description>
      <pubDate>Fri, 11 Mar 2016 20:19:26 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2016/can-i-track-it/</guid>
    </item>
    <item>
      <title>Google Maps - The Bits They Don&#39;t Tell You</title>
      <link>https://chrissmith.xyz/blog/2016/google-maps-the-bits-they-dont-tell-you/</link>
      <description>&lt;p&gt;I&#39;ve done quite a lot of work with the Google Maps JavaScript API in the last year or so. I think I&#39;ve picked up quite a bit along the way, which you won&#39;t find in the official reference guide.&lt;/p&gt;
&lt;p&gt;When I first started working with it, one of my favourite things was the excellent documentation that came with it. Sadly, since the shift to Material Design, it&#39;s now very difficult to navigate and find anything. In fact, I&#39;ve pretty much given up on it. It&#39;s a lot easier to just use Stack Overflow.&lt;/p&gt;
&lt;p&gt;Here are some fairly basic things I found, which, depending on your project, might make life easier.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Use a map object&lt;/strong&gt;
Using an overarching object to hold anything map related - data arrays, functions, etc. really helps when you&#39;re using dynamic data or lots of other JavaScript. It&#39;s basically just a namespace, package or module.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Push overlays into arrays&lt;/strong&gt;
When you add any overlay, for example a marker or polygon, the normal process is to read the geo data out of an object or array and use it to add the overlays. However, if you then want to interact with those overlays you have no way of selecting them. When you create an overlay push it into an array. That way you can loop through the items or select one by its index.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Add key or id property to get an overlay easily&lt;/strong&gt;
In addition to adding an overlay to an array you can give it its own custom property like an id or key so that you can select it without knowing its index. The Google Maps overlay objects, which can have properties like fillColor, map, position, etc. are actually just JavaScript objects so you can add your own properties. You can then use filter() to access an individual overlay from the array or you can alias it with a variable.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Use polygons appropriate for zoom range&lt;/strong&gt;
If you define a polygon it will work at any zoom range. For your map usage it&#39;s worth considering if you need to allow the full zoom range to be used. It might be easier to limit it. Imagine a polygon for the outline of France. If you&#39;re zoomed right out, looking at the world you can get away with just a hexagon shape. If you zoom in close you need to pick out each little twist and turn in the coastline. See what you need and use simplified polygons for speed and performance where possible.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Use dynamic SVGs as icons&lt;/strong&gt;
You can use your own image files as markers instead of the standard pin. However, these don&#39;t have to be static image files. You can create your own function which takes parameters for colours or values and uses these to return an SVG including these details. You can then set this function as the icon image.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Set bounds and extend them&lt;/strong&gt;
When you create a map, also create a bounds object. This holds location data for the top right (NE) and bottom left (SW) of a box, which determines the portion of the map shown on screen. It manages the zoom level for you. Whenever you add a new overlay to your map you can extend these bounds so that all of your overlays will always be shown.&lt;/p&gt;
</description>
      <pubDate>Wed, 09 Mar 2016 18:06:04 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2016/google-maps-the-bits-they-dont-tell-you/</guid>
    </item>
    <item>
      <title>Tools of the Trade</title>
      <link>https://chrissmith.xyz/blog/2016/tools-of-the-trade/</link>
      <description>&lt;p&gt;I thought I&#39;d list some of the web development tools I use. Not the cool stuff I&#39;ve recently found or wish I understood but the actual things I go to or reach for when I need to get a job done.&lt;/p&gt;
&lt;p&gt;Everyone has their own preferred code editor, which does the bulk of the work. And I&#39;m pretty sure everyone uses their browser developer tools too. This is more the little tools for very specific jobs.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://compressor.io/compress&quot; target=&quot;_blank&quot;&gt;Compressor.io&lt;/a&gt;
I use this for optimising images - compressing and removing any junk. The site has a very slick UI, which makes it fun to use.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://websemantics.co.uk/online_tools/image_to_data_uri_convertor/&quot; target=&quot;_blank&quot;&gt;Web Semantics Data URI Conversion&lt;/a&gt;
This lets you upload an image and get back a data URI. It also provides the code for setting it as an image or the CSS for a background image, which saves extra time.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.patternify.com/&quot; target=&quot;_blank&quot;&gt;Patternify&lt;/a&gt;
It&#39;s great fun creating simple repeating background patterns as data URIs with this site.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://subtlepatterns.com/&quot; target=&quot;_blank&quot;&gt;Subtle Patterns&lt;/a&gt;
This is what it sounds like - understated background tile images.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.patterncooler.com/&quot; target=&quot;_blank&quot;&gt;Pattern Cooler&lt;/a&gt;
A more advanced background pattern creator with a lot of customisations and options. Used for the background pattern seen on this site on larger screens.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://unsplash.com/&quot; target=&quot;_blank&quot;&gt;Unsplash&lt;/a&gt;
Free high quality photos, mainly outdoor scenes.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://svg-edit.googlecode.com/svn-history/r1771/trunk/editor/svg-editor.html&quot; target=&quot;_blank&quot;&gt;SVG-Edit&lt;/a&gt;
An online SVG editor. There are plenty of others with nicer UIs and easier URLs but this one has all the right options for me.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://tools.dynamicdrive.com/favicon/&quot; target=&quot;_blank&quot;&gt;Dynamc Drive&#39;s Favicon Generator&lt;/a&gt;
I&#39;ve been using this one from the very start and it still holds up as a great tool for me. There are too many favicon generators that try to do too much - spitting out huge files with 20 lines of HTML.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://chrome.google.com/webstore/detail/advanced-rest-client/hgmloofddffdnphfgcellkdfbfbjeloo&quot; target=&quot;_blank&quot;&gt;Advanced REST Client&lt;/a&gt;
This is a Chrome app, which allows you to play around with http requests.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.webpagetest.org/&quot; target=&quot;_blank&quot;&gt;Web Page Test&lt;/a&gt;
The site&#39;s ugly as hell but works a treat for providing loading times and performance data.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://developers.google.com/speed/pagespeed/insights/&quot; target=&quot;_blank&quot;&gt;Google PageSpeed Insights&lt;/a&gt;
Get Google suggestions for improving your page load times. Useful for both performance and SEO.&lt;/p&gt;
&lt;p&gt;I recommend Louis Lazaris&#39; &lt;a href=&quot;https://webtoolsweekly.com/&quot; target=&quot;_blank&quot;&gt;Web Tools Weekly&lt;/a&gt;, a weekly email with JavaScript tutorials and links to New tools.&lt;/p&gt;
</description>
      <pubDate>Sun, 06 Mar 2016 12:52:30 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2016/tools-of-the-trade/</guid>
    </item>
    <item>
      <title>Learning Flexbox</title>
      <link>https://chrissmith.xyz/blog/2016/learning-flexbox/</link>
      <description>&lt;p&gt;I&#39;ve just, finally, learned how to use the flexible box layout, more commonly known as Flexbox. I&#39;m not going to explain it as there are other sites that can do a far better job of that but just wanted to share some excellent resources for learning it as painlessly as possible.&lt;/p&gt;
&lt;p&gt;I&#39;ve delayed on learning it for what feels like years as I&#39;ve had to support older browsers and trying to provide alternative layouts for old and new was just too much of a maintenance headache. Now I&#39;ve learned it there&#39;s no looking back.&lt;/p&gt;
&lt;p&gt;Here are 3 excellent resources to help learn it. They&#39;re all quite different but used together cover everything you could need.&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://flexbox.io/&quot; target=&quot;_blank&quot;&gt;Flexbox.io&lt;/a&gt;&lt;/h3&gt;
This is a series of free video tutorials by &lt;a href=&quot;https://twitter.com/wesbos&quot; target=&quot;_blank&quot;&gt;Wes Bos&lt;/a&gt;. Each video is short and focuses on one step, which makes it easy to digest. It&#39;s very well explained, gives real examples and even details setting up AutoPrefixer to make it more cross browser compatible. I&#39;d say this is the best place to start.&lt;/li&gt;
	&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.flexboxdefense.com/&quot; target=&quot;_blank&quot;&gt;FlexboxDefense.com&lt;/a&gt;&lt;/h3&gt;
This site by &lt;a href=&quot;https://twitter.com/ChanningAllen&quot; target=&quot;_blank&quot;&gt;Channing Allen&lt;/a&gt; is a game that gets you to use your flexbox knowledge to position towers to defend against attackers. It&#39;s got 10 levels which increase in difficulty. It&#39;s fun and gives some good practice of actually using the code and seeing the results.&lt;/li&gt;
	&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://css-tricks.com/snippets/css/a-guide-to-flexbox/&quot; target=&quot;_blank&quot;&gt;CSS Tricks Complete Guide to Flexbox&lt;/a&gt;&lt;/h3&gt;
This is a great resource for reference as it lists everything you might want to know about flexbox all in one page. It includes nice graphics which explain the flow of content, Codepen code examples, details on the background, browser compatibility. Definitely one to bookmark. Great job as ever, &lt;a href=&quot;https://twitter.com/chriscoyier&quot; target=&quot;_blank&quot;&gt;Chris Coyier&lt;/a&gt;!&lt;/li&gt;
&lt;/ol&gt;
</description>
      <pubDate>Fri, 04 Mar 2016 21:28:10 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2016/learning-flexbox/</guid>
    </item>
    <item>
      <title>Loading More Items</title>
      <link>https://chrissmith.xyz/blog/2016/loading-more-items/</link>
      <description>&lt;p&gt;What&#39;s the best way of loading more items on screen in terms of user experience and performance - &amp;quot;infinite&amp;quot; scroll, pagination or a simple &amp;quot;load more&amp;quot; option? Here&#39;s a quick look and pros and cons of each.&lt;/p&gt;
&lt;h3&gt;Infinite Scroll&lt;/h3&gt;
Infinite scroll is the name given to a web design pattern where scrolling to the bottom of the screen loads more records. It&#39;s most common in streams like on Facebook and Twitter.
&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;
Done well it&#39;s a nice seemless flow, moving very smoothly from one set of items to the next.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;
It can be hard to navigate back up the list. Having so many items on screen at once can be confusing and slow everything down. The list has to be loaded in order - it&#39;s not possible to skip to the end. It&#39;s not infinite - there is always a finite number of records - just a pet hate of mine.&lt;/p&gt;
&lt;h3&gt;Pagination&lt;/h3&gt;
Pagination is the practice of breaking a large list down into pages and only showing a fixed number of records at a time. It typically has links at the bottom to navigate between pages and previous and next links. It often features text to help explain what is being shown, e.g. &quot;Showing records 21-40 of 165&quot;.
&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;
It&#39;s very clear. The user is not presented with too much information at once. This keeps the DOM light and the screen fast. The user knows where he/she is in the list and can make an educated guess on jumping to other pages. If the list is in alphabetical order and has 10 pages, you can assume that something beginning with M will be roughly in the middle, page 5 or 6.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;
Seeing that there are lots of pages can be off-putting.&lt;/p&gt;
&lt;h3&gt;Load More&lt;/h3&gt;
The Load More option is like Infinite Scroll but instead of automatically loading more as the user scrolls down you offer a button or link to load the next set of items. This is commonly seen at the end of image search lists.
&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;
It puts the user in control - they don&#39;t accidentally load content they don&#39;t really want using up bandwidth on mobile. It doesn&#39;t give a sense of how much data there is in the pipeline so doesn&#39;t scare the user away from loading more.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;
Sometimes not having a sense of the number of records can be a bad thing. As with Infinite Scroll, the list has to be loaded in order - it&#39;s not possible to skip to the end.&lt;/p&gt;
</description>
      <pubDate>Thu, 03 Mar 2016 18:03:38 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2016/loading-more-items/</guid>
    </item>
    <item>
      <title>Boosting Web Performance</title>
      <link>https://chrissmith.xyz/blog/2016/boosting-web-performance/</link>
      <description>&lt;p&gt;One of the areas of front end development I&#39;ve really got into in the last year or so is performance. It&#39;s always been there in the background (along with SEO and accessibility) but it seems to have a lot more focus in the web community lately.&lt;/p&gt;
&lt;p&gt;For a while I&#39;ve been looking at different ways to speed up various sites I work on. This site has given me a perfect guinea pig for trying out some different techniques. Let&#39;s give it a boost! Oooosh!&lt;/p&gt;
&lt;h3&gt;Static&lt;/h3&gt;
My first idea for making this site super fast to load was to make all of the pages static. I started off by just making a few pages but soon realised that as things grew and I wanted to make design changes it just wasn&#39;t scalable. It was fast though. If I was building a simple site with only a handful of pages this is the way to go.
&lt;h3&gt;Jekyll&lt;/h3&gt;
To try to get the best of both worlds, static for speed and CMS for convenience, I moved on to using &lt;a href=&quot;https://jekyllrb.com/&quot; target=&quot;_blank&quot;&gt;Jekyll&lt;/a&gt;, a static site generator. After jumping through a lot of hoops I got it set up. It works really well and if you&#39;re planning to update a site from a single machine I&#39;d say this is the perfect solution.
&lt;h3&gt;WordPress&lt;/h3&gt;
For various reasons I moved back to good old uncle &lt;a href=&quot;https://wordpress.org/&quot; target=&quot;_blank&quot;&gt;WordPress&lt;/a&gt;. It&#39;s so easy to update from anywhere, which means I actually do it, plus I feel that it&#39;s become so big in the web industry (almost its own industry) that I can&#39;t really afford not to know my way around it.
&lt;p&gt;So, my new challenge is to make my WordPress site fast. There are various well renowned caching plugins, e.g. &lt;a href=&quot;https://wordpress.org/plugins/w3-total-cache/&quot; target=&quot;_blank&quot;&gt;W3 Total Cache&lt;/a&gt;, which would effectively turn my PHP into static pages. Unfortunately, these don&#39;t seem to work with my &lt;a href=&quot;https://codex.wordpress.org/Create_A_Network&quot; target=&quot;_blank&quot;&gt;multisite&lt;/a&gt; setup so I&#39;ve tried something different.&lt;/p&gt;
&lt;h3&gt;Cloudflare&lt;/h3&gt;
I&#39;ve routed my site through &lt;a href=&quot;https://www.cloudflare.com/&quot; target=&quot;_blank&quot;&gt;Cloudflare&lt;/a&gt;. It&#39;s a website fronting service which aims to improve performance and security. They host your site on various servers around the world so you get the benefits of a CDN - fast delivery to far flung parts of the world. They concatenate and minify static files for you - one less job. They also handle security threats and high spikes in traffic so your site doesn&#39;t go down. As if that wasn&#39;t enough, they also serve your files over https - cheaper than SSL hosting and great for SEO.
&lt;p&gt;So far so great. Definitely worth a look on top of whatever other optimisations you&#39;re doing. :)&lt;/p&gt;
</description>
      <pubDate>Wed, 10 Feb 2016 17:40:42 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2016/boosting-web-performance/</guid>
    </item>
    <item>
      <title>Bilingual Equality with a Splash Page</title>
      <link>https://chrissmith.xyz/blog/2016/bilingual-equality-with-a-splash-page/</link>
      <description>&lt;p&gt;I&#39;ve worked on a few education sites in Wales and bilingualism is one of the major challenges for any public sector site.&lt;/p&gt;
&lt;p&gt;A multilingual site isn&#39;t so hard. Most content management systems offer language switching - being on a page in one language and hopping across to view the equivalent piece of content in another. The difficulty comes with entering the site or managing the landing page experience.&lt;/p&gt;
&lt;p&gt;So, on your bilingual site, what do you put on your home page? Most content management systems are set up to use a default or primary language with others as secondary options. They&#39;re not treated equally. In Wales we&#39;re supposed to give both Welsh and English equal status.&lt;/p&gt;
&lt;p&gt;At one point I toyed with the idea of having bilingual pages - a 2 column layout with the 2 versions side by side. This is common in print and it works pretty well. On web pages it&#39;s not so easy. Space can be very limited, especially on mobile. Loading and displaying additional content that will not be consumed is not really practical. It halves the value of your site - that&#39;s value in real monetary terms if you&#39;re paying for data downloaded. The other main point is that web pages just don&#39;t work that way. A page needs to have a language set so that it can be searched and indexed by search engines. As soon as we mix languages, we&#39;re probably killing any potential search rankings.&lt;/p&gt;
&lt;p&gt;I&#39;ve come up with a possible solution. I&#39;m not sure it would work in all cases but for the school website I&#39;m working on now it seems to tick all the boxes. I use a Splash Page. It&#39;s normal use would be for special promotions. It&#39;s a screen which interrupts your browsing before allowing you to continue to your usual entry page. Rather than a static promotional message I&#39;m reading in the title of the target page in both languages and presenting them as options. So, the user chooses whether to continue in Welsh or English. Now, here&#39;s the clever bit. The user&#39;s language preference is stored in the browser (localStorage) and is used on future visits. If a preference has been set then the Splash Page will not appear again on that browser, within a specified time frame.&lt;/p&gt;
&lt;p&gt;Using this Splash Page means that the user is never presented with a monolingual page without having first made a choice. We have achieved equality for both languages whilst not harming our search engine rankings. :)&lt;/p&gt;
</description>
      <pubDate>Mon, 18 Jan 2016 23:14:08 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2016/bilingual-equality-with-a-splash-page/</guid>
    </item>
    <item>
      <title>Website Redesign - chrissmith.xyz</title>
      <link>https://chrissmith.xyz/blog/2016/website-redesign-chrissmith-xyz/</link>
      <description>&lt;p&gt;Over the last couple of months of 2015 and the start of 2016 I decided to redesign this site. There wasn&#39;t anything particularly wrong with it before from a user&#39;s point of view but from an author&#39;s point of view I felt I could do better.&lt;/p&gt;
&lt;p&gt;The site was built using &lt;a href=&quot;https://jekyllrb.com/&quot; target=&quot;_blank&quot;&gt;Jekyll&lt;/a&gt;, which is a static site generator. You make changes on your local machine and everything gets rebuilt as static files. This is great for performance as static pages are much faster. The downside for me was that it meant only being able to publish blog posts or pages from that one machine. #firstworldproblems :)&lt;/p&gt;
&lt;p&gt;My biggest issue with having my own site is giving it the love it deserves. Making time to write content is definitely the number one blocker for me. If I could make it as easy as possible to write content from multiple devices that would go a long way to making it work for me. I decided to go back to good old &lt;a href=&quot;https://en-gb.wordpress.org/&quot; target=&quot;_blank&quot;&gt;WordPress&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I now publish from my laptop as before but, as it&#39;s all web based, I can just log on anywhere and write a draft. The &lt;a href=&quot;https://www.amazon.co.uk/Fire-Display-Wi-Fi-GB-Includes/dp/B00Y3TM6CO&quot; target=&quot;_blank&quot;&gt;Amazon Fire tablet&lt;/a&gt; (forked Android) has a WordPress app which allows me to write locally and sync at my convenience. I don&#39;t think I&#39;d really choose to write blog posts from my phone but if I ever needed to make a change, e.g. spotted an embarrassing typo, I could.&lt;/p&gt;
&lt;p&gt;As a developer using something built on PHP and MySql is nowhere near as cool as Ruby and no database but who actually cares. Loads of great sites I use day-to-day are built on WordPress, like &lt;a href=&quot;https://css-tricks.com/&quot; target=&quot;_blank&quot;&gt;CSS Tricks&lt;/a&gt;. If it&#39;s good enough for them, it&#39;s good enough for me.&lt;/p&gt;
&lt;p&gt;Adding or customising themes is very simple. I&#39;m using the default &lt;a href=&quot;https://wordpress.org/themes/twentyfifteen/&quot; target=&quot;_blank&quot;&gt;Twenty Fifteen&lt;/a&gt; theme but have added my own little child theme to customise it beyond just colours and image background choices. I&#39;m using a Google Font called &lt;a href=&quot;https://www.google.com/fonts/specimen/Anton&quot; target=&quot;_blank&quot;&gt;Anton&lt;/a&gt; for headings plus I&#39;ve changed some of the spacing and played with the perspective of the sidebar.&lt;/p&gt;
&lt;p&gt;The vibrant pink hasn&#39;t changed.&lt;/p&gt;
</description>
      <pubDate>Wed, 13 Jan 2016 18:00:29 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2016/website-redesign-chrissmith-xyz/</guid>
    </item>
    <item>
      <title>Setting Default Styling for Custom UI Components</title>
      <link>https://chrissmith.xyz/blog/2016/setting-default-styling-for-custom-ui-components/</link>
      <description>&lt;p&gt;I thought I&#39;d share a challenge I&#39;m facing at the moment. A lot of modern JavaScript frameworks like React and Angular encourage building reusable UI components. Using JavaScript and HTML templates seems like an excellent approach to development on larger sites but styling these components can bring a few issues.&lt;/p&gt;
&lt;p&gt;Browsers can handle styling standard HTML web components, like &amp;lt;select&amp;gt; or &amp;lt;button&amp;gt;. They may vary in how they display these but they all have a default way which can then be overwritten with CSS. This is stored as a kind of internal CSS class in the browser and is easy to overwrite as it has almost zero specificity. Adding an element selector &#39;select&#39;, a class &#39;.picker&#39; or an id &#39;#picker&#39; will easily take control over the styling.&lt;/p&gt;
&lt;p&gt;The problem arises when we create custom components that don&#39;t have any default, zero specificity styling. Any styling that we do add when we design components has specificity so we immediately have a fight on our hands for which styling declaration gets control. We need some level of default styling, usually for layout as much as anything, to ensure that the browser cannot just show a mess of HTML elements.&lt;/p&gt;
&lt;p&gt;Here are a few examples of how default component styling could be set and the problems associated with each approach.&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;
&lt;h3&gt;Setting the CSS in an external stylesheet&lt;/h3&gt;
We set the styling in its own CSS file. I&#39;d say that this is the approach used by most UI tools like Bootstrap or jQuery UI. Various HTML elements in the component are given classes, which can be overwritten.
&lt;p&gt;The problem is that they can only be overwritten by using higher specificity or by making sure that the overwriting style comes after the external CSS in the document&#39;s source order. It also means an additional HTTP request to load a usually small amount of styling data.&lt;/p&gt;&lt;/li&gt;&lt;p&gt;&lt;/p&gt;
&lt;li&gt;
&lt;h3&gt;Setting the style in a style attribute&lt;/h3&gt;
We could add style attributes directly into the HTML tags. The problem here is obvious - super high specificity. This makes the styling very difficult to overwrite. You&#39;re pretty much forced into using &#39;!important&#39; declarations in your CSS, which not only feels wrong but really leaves you with nowhere to go.
&lt;p&gt;It goes against the separation of concerns - content and styling but as this is intended to be default styling, which we would hope to overwrite, I&#39;m not sure this matters.&lt;/p&gt;&lt;/li&gt;&lt;p&gt;&lt;/p&gt;
&lt;li&gt;
&lt;h3&gt;Setting the style in a HTML &amp;lt;style&amp;gt; tag&lt;/h3&gt;
We could place a block of HTML with &amp;lt;style&amp;gt; tags directly before or after the component HTML so that it effectively ships together. Placing &amp;lt;style&amp;gt; tags in the &amp;lt;body&amp;gt; was invalid in HTML4 but, if I&#39;ve understood it correctly, can be used in HTML5 by using the scoped attribute, e.g. &amp;lt;style type=&quot;text/css&quot; scoped&amp;gt;&amp;lt;/style&amp;gt;. Browser support for this to be properly valid is not great at the time of writing (early 2016) - we get warning messages in consoles or code editors - but it seems to display as intended.
&lt;p&gt;The problem with this approach is that the style is declared in the &amp;lt;body&amp;gt; whereas the overwriting CSS is probably declared in the &amp;lt;head&amp;gt; and so will not overwrite it without upping the specificity.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.w3.org/TR/REC-html40/present/styles.html&quot; target=&quot;_blank&quot;&gt;W3C Recommendation - Stylesheets
&lt;/a&gt;&lt;a href=&quot;https://www.w3.org/TR/html-markup/style.html#style.attrs.scoped&quot; target=&quot;_blank&quot;&gt;W3C Recommendation - Style Scoped&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;p&gt;&lt;/p&gt;
&lt;li&gt;
&lt;h3&gt;Setting the style with JavaScript&lt;/h3&gt;
The final option is to set styling using JavaScript, which effectively just inserts style attributes into the component&#39;s HTML elements like in approach 2.&lt;/li&gt;
&lt;/ol&gt;
I&#39;m wondering if there may be a solution where we have a default styles object which defines style properties in our existing component JavaScript file. We then check to see what styling is applied using the browser&#39;s getComputedStyle() function. For each of the properties we check if a rule is already set, presumably by CSS that is in the &amp;lt;head&amp;gt;, and if not we apply the style from the object. It&#39;s almost like required validation for styling. I don&#39;t imagine it&#39;s going to be very efficient but it may be a way of ensuring a minimum level of styling without restricting additional styling via CSS. Assuming that our script file is at the end of the &amp;lt;body&amp;gt;, by using only the existing resources we could save an additional HTTP request.
</description>
      <pubDate>Sun, 10 Jan 2016 22:24:32 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2016/setting-default-styling-for-custom-ui-components/</guid>
    </item>
    <item>
      <title>What I Learned in 2015</title>
      <link>https://chrissmith.xyz/blog/2016/what-i-learned-in-2015/</link>
      <description>&lt;p&gt;I thought I&#39;d do another quick run-through of what I&#39;ve picked up this year. It feels good to show myself that I&#39;m still learning at a healthy pace.&lt;/p&gt;
&lt;h3&gt;SVG&lt;/h3&gt;
I&#39;ve started using SVG more, creating some simple charts and building dynamic graphics for use with Google Maps. I made markers or pins, which have colours and characters set dynamically according to data. I think I&#39;ve finally got my head around the whole viewBox, which took me a while. &lt;a href=&quot;https://css-tricks.com/search-results/?q=svg&quot; target=&quot;_blank&quot;&gt;CSS Tricks&lt;/a&gt; provided me with some &lt;a href=&quot;https://css-tricks.com/search-results/?q=svg&quot; target=&quot;_blank&quot;&gt;very useful SVG tutorials&lt;/a&gt; and introduced me to the work of &lt;a href=&quot;https://sarasoueidan.com/&quot; target=&quot;_blank&quot;&gt;Sara Soueidan&lt;/a&gt;.
&lt;h3&gt;Angular.js&lt;/h3&gt;
I&#39;ve been tinkering with &lt;a href=&quot;https://angularjs.org/&quot; target=&quot;_blank&quot;&gt;Angular&lt;/a&gt; for a while but have really got into using it day-to-day this year. I found it hard at first because it&#39;s so different to using native JavaScript or jQuery to manipulate the DOM. In Angular you basically set conditions in the HTML, e.g. show this when the data is that, and then to make things happen you just change the data. The data changes and the UI updates. It means you&#39;re not making data changes and UI changes - just change the data and Angular looks after the UI. Once you&#39;ve got that it&#39;s actually a lot easier to manage than writing an app with jQuery.
&lt;h3&gt;React.js&lt;/h3&gt;
I&#39;ve done my first project using &lt;a href=&quot;https://facebook.github.io/react/&quot; target=&quot;_blank&quot;&gt;React&lt;/a&gt;. This is a very clever framework for updating the UI as quickly as possible. It checks what actually needs to change on screen and only updates the HTML nodes that require a change, making the UI very fast and, well, reactive. It&#39;s based on building components which each have their own properties and state. The component or modular approach certainly feels like the way forward for building UIs.
&lt;h3&gt;Jekyll&lt;/h3&gt;
I built the previous incarnation of this website using &lt;a href=&quot;https://jekyllrb.com/&quot; target=&quot;_blank&quot;&gt;Jekyll&lt;/a&gt;. It&#39;s a static site generator. It works in much the same way as any content management system with templates and a build process but spits out static HTML so it&#39;s faster for the user. It took a lot of setting up on Windows and involved some scary new stuff for me, like Ruby, Python and using the command line. It is an amazing bit of software for building fast sites and very flexible. Definitely worth trying. I eventually moved away from it and back to WordPress as it was just easier to update - I can update from any device anywhere without having to have the complicated local set up. As my content is mainly just text, I didn&#39;t feel the performance gains balanced out the usability for me as an author.
&lt;h3&gt;Markdown&lt;/h3&gt;
Using Jekyll also introduced me to using markdown. It&#39;s a quick way of writing HTML without having to use tags. It keeps the content clean and easy to read, whilst containing formatting. It kind of lets you write HTML without having to break your creative flow to think about formatting. It also enables non HTML savvy authors to publish formatted content easily.
&lt;h3&gt;New JavaScript Syntax - EcmaScript 6&lt;/h3&gt;
I haven&#39;t used it yet but started reading about ES6. There are a few good introductory articles, which show off some of the new features without getting too bogged down in the details. Here&#39;s a &lt;a href=&quot;https://www.felixrieseberg.com/ecmascript6-introduction/&quot; target=&quot;_blank&quot;&gt;good basic ES6 intro&lt;/a&gt;. It feels like a lot to learn but it becomes evident very quickly that we&#39;ll be able to write less code and it&#39;ll be easier to understand. Win win.
&lt;h3&gt;Google Analytics Event Tracking&lt;/h3&gt;
I&#39;ve used Google Analytics for years but have just discovered how to use event tracking. I can now track clicks on a particular UI element to see how it&#39;s used, check pre-defined user preferences by reading data out of the browser&#39;s localStorage, measure download numbers for PDF documents. It&#39;s opening the doors to a lot of previously missing data with regards to user behaviour and can help me make better decisions on designing the user experience.
&lt;h3&gt;Responsive Web Design&lt;/h3&gt;
I&#39;ve made big strides forward this year with responsive design. I&#39;m starting, late I know, to think about it in everything I do. It&#39;s a lot more work but leads to much more usable UIs and often forces me to keep the design simpler than I would otherwise, which is probably a good thing.
&lt;h3&gt;Bootstrap&lt;/h3&gt;
I&#39;ve actively avoided &lt;a href=&quot;https://getbootstrap.com/&quot; target=&quot;_blank&quot;&gt;Bootstrap&lt;/a&gt; for the last few years. I always had 2 major concerns with it: 1) that my sites would end up looking the same as everyone else&#39;s and 2) that I was loading up a hefty framework and then only using a fraction of it, which would be very wasteful.
&lt;p&gt;A colleague reintroduced me to it and I was delighted to find that it&#39;s now possible to &lt;a href=&quot;https://getbootstrap.com/customize/&quot; target=&quot;_blank&quot;&gt;create customised builds&lt;/a&gt; so you can choose the parts you want to include (no waste) and even set colour schemes, default padding, etc. in the build, replacing the defaults, so there&#39;s less needed to overwrite in a custom theme.&lt;/p&gt;
&lt;p&gt;I&#39;ve started using it as its grid layout makes responsive design so much easier than handling each page element and I know that the ready made components and UI elements are accessible where my own might not be.&lt;/p&gt;
&lt;h3&gt;Codepen&lt;/h3&gt;
And finally, &lt;a href=&quot;https://codepen.io/&quot; target=&quot;_blank&quot;&gt;Codepen&lt;/a&gt;. I&#39;ve covered this in another post, &lt;a href=&quot;https://chrissmith.xyz/blog/developing-in-codepen/&quot; target=&quot;_blank&quot;&gt;Developing in Codepen&lt;/a&gt;. In short, I use it every day, it&#39;s awesome.
</description>
      <pubDate>Sat, 02 Jan 2016 12:09:59 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2016/what-i-learned-in-2015/</guid>
    </item>
    <item>
      <title>Easier Colours in Web Design</title>
      <link>https://chrissmith.xyz/blog/2015/easier-colours-in-web-design/</link>
      <description>&lt;p&gt;In the last couple of years I&#39;ve changed the way I work with colours in websites. I&#39;ve realised that the number of colours available to us as designers or developers is actually kind of ridiculous and that we&#39;re making life harder than it needs to be.&lt;/p&gt;
&lt;p&gt;Whether you use RGB(A) or Hexidecimal notation the number of colours available, if I&#39;ve worked it out correctly, is:&lt;/p&gt;
&lt;blockquote&gt;256 * 256 * 256 = 16,777,216 colours&lt;/blockquote&gt;
That&#39;s a lot of colours.
&lt;p&gt;Whilst having so many colours available for display is brilliant for viewing high quality photos or creating super smooth gradients, we just don&#39;t need to work at that level when assigning colours in our day to day work.&lt;/p&gt;
&lt;p&gt;I&#39;ve moved to using short form Hex codes, e.g. #fff, for everything. It&#39;s not like this leaves you short of choice. In fact, there are still a cool 4,096 colours to pick from, which is more than enough to make my brain hurt.&lt;/p&gt;
&lt;blockquote&gt;16 x 16 x 16 = 4,096 colours&lt;/blockquote&gt;
I&#39;ve even gone a stage further and replaced old long form Hex colours with the my new found short form. It&#39;s just a case of rounding the values up or down to their nearest whole increment. Values 0-7 are rounded down, 8-f are rounded up. So, #5ba546 becomes #6a4. Can you tell the difference?
&lt;div style=&quot;display: inline-block; inline-size: 30%; background-color: #5ba546; color: #fff; margin-inline-end: .5em; padding: .5em;&quot;&gt;#5ba546&lt;/div&gt;
&lt;div style=&quot;display: inline-block; inline-size: 30%; background-color: #6a4; color: #fff; padding: .5em; margin-block-end: 1em;&quot;&gt;#6a4&lt;/div&gt;
Maybe you can tell the difference seeing them side by side. Would you feel confident you could tell me which one it was if I only showed you the one? Does it matter anyway?
&lt;p&gt;I would argue that the colour specified and the colour actually seen are never an exact match. A device&#39;s display settings - brightness, number of colours, saturation, warmth, etc. can vary so much that is a true colour even really a thing any more? It&#39;s more the relationship to other colours that matters than the representation of a single colour on its own.&lt;/p&gt;
&lt;p&gt;I wouldn&#39;t say there are major gains to be had by shortening the Hex codes but any removal of unnecessary complexity has to be a good thing, right? It&#39;s less characters to type - hardly a major victory - but, more importantly, quite a lot easier to remember each colour, which means that we type the right thing from memory more often and don&#39;t have to spend so much time referring back to style guides for commonly used colours.&lt;/p&gt;
&lt;p&gt;So, which is it, #5ba546 or #6a4?&lt;/p&gt;
&lt;div style=&quot;display: inline-block; inline-size: 30%; background-color: #6a4; color: #fff; padding: .5em; margin-block-end: 1em;&quot;&gt;#?&lt;/div&gt;
</description>
      <pubDate>Thu, 24 Dec 2015 16:30:21 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2015/easier-colours-in-web-design/</guid>
    </item>
    <item>
      <title>Developing in Codepen</title>
      <link>https://chrissmith.xyz/blog/2015/developing-in-codepen/</link>
      <description>&lt;p&gt;A look at why and how I use Codepen for front end development work.&lt;/p&gt;
&lt;h3&gt;Background&lt;/h3&gt;
I work on a web app with a development team. We use &lt;a href=&quot;https://angularjs.org/&quot; target=&quot;_blank&quot;&gt;AngularJS&lt;/a&gt; with a RESTful API. My role is looking at the design and UX side of things and scoping out how a new feature will look and behave in a web browser, or, I should say, in various browsers at different screen sizes.
&lt;p&gt;I generally do my work up front. I&#39;ve always been a design in HTML and CSS kind of guy. To me, with my skill set, working in a graphics editor takes as long as coding it so it makes little sense for me to do the work twice.&lt;/p&gt;
&lt;p&gt;Until recently, I&#39;ve been using static HTML and then another developer has added the binding and data. Where the feature is on a new screen I can go a step further and create a dummy data object, to represent the data returned from the API, and actually do the binding as well as create any custom behaviour.&lt;/p&gt;
&lt;p&gt;Working on existing screens has been much more difficult. It&#39;s almost impossible to add new data, binding and behaviours without breaking the existing code. To use a dummy data object I need to intercept the real data retrieval and replace the object, which stops the page working when wired up again. However I work things, I&#39;m having to check in code which is not releasable.&lt;/p&gt;
&lt;h3&gt;A new way of working&lt;/h3&gt;
I&#39;ve started using &lt;a href=&quot;https://codepen.io/&quot; target=&quot;_blank&quot;&gt;Codepen&lt;/a&gt; to abstract away the new feature. I set up a new pen, import any existing dependencies and then create the HTML, CSS and JavaScript for the new feature in isolation.
&lt;p&gt;This means that the original project code does not get touched and broken. As the next developer brings in any model/schema changes he/she can bring in my front end code so we don&#39;t have any breaking check-ins.&lt;/p&gt;
&lt;p&gt;By importing the dependencies - JavaScript libraries, CSS - we avoid any clashes or inheritance issues and additional work trying to integrate my code.&lt;/p&gt;
&lt;p&gt;It also means I can give the new feature my full attention without having to use other parts of the screen, for example, if I&#39;m working on a modal window, I don&#39;t have to go through the usual page processes in order to call it.&lt;/p&gt;
&lt;p&gt;I&#39;m using &lt;a href=&quot;https://codepen.io/&quot; target=&quot;_blank&quot;&gt;Codepen&lt;/a&gt; in the way it was intended, as a front end playground, an environment where I can experiment with different ways of doing things. The results are displayed in a frame, updated instantly as you type, which makes working much faster - no more manual refreshing or rebuilding.&lt;/p&gt;
&lt;p&gt;From what I&#39;ve described up to this point, this abstraction could be done by making a copy of the page but copying the HTML page, the CSS and JavaScript and changing all of the references between these files is quite a headache. Believe me, I&#39;ve been there enough times.&lt;/p&gt;
&lt;p&gt;One of the massive advantages of &lt;a href=&quot;https://codepen.io/&quot; target=&quot;_blank&quot;&gt;Codepen&lt;/a&gt; for a designer is the ability to fork pens, so you just hit one button and you&#39;ve got an exact copy of the pen you were working in, making it very easy to create a few variations of a design.&lt;/p&gt;
&lt;p&gt;As each pen is available on a public URL it&#39;s easy to share designs with colleagues or clients and they can see a working prototype - much better than a static screenshot. It also means that links can be embedded in documentation. Personally, I feel that now web animation has become mainstream, it&#39;s important to be able to show how screen elements transition between states, how things appear/disappear and demonstrate where the user&#39;s attention is drawn through processes. Static screenshots just don&#39;t cut it any more.&lt;/p&gt;
&lt;p&gt;Final point. Designing in the browser with work stored in the cloud is awesome for design. I could be out and about and suddenly see some inspiration for something I&#39;m working on or get a new idea. Rather than hope I&#39;ll remember it, I can quickly create a new pen or fork an existing one and add some code or notes there and then from a phone or tablet. I don&#39;t have to hope I&#39;ll remember or wait until I&#39;m back at my desktop. It&#39;s exactly what the web should be.&lt;/p&gt;
</description>
      <pubDate>Sun, 13 Dec 2015 22:09:41 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2015/developing-in-codepen/</guid>
    </item>
    <item>
      <title>Questioning the UX of an App I&#39;ve Never Seen</title>
      <link>https://chrissmith.xyz/blog/2015/questioning-the-ux-of-an-app-ive-never-seen/</link>
      <description>&lt;p&gt;This is an odd one. There&#39;s an App out there called Tinder. I&#39;ve never seen it but have heard a few people talking about it on the radio and on podcasts. Without even seeing it for myself I&#39;m questioning its usability. Is that normal?&lt;/p&gt;
&lt;p&gt;From what I understand it&#39;s kind of a dating service where the user is shown photos of other users in his/her vicinity. The idea is you then basically accept or reject each and if 2 users accept each other something happens - I don&#39;t know what - they didn&#39;t talk about that bit. I&#39;d guess some kind of notification or they go through to the next round or, at least, some kind of progress. Anyway, the point here, and the bit these conversations have focused on, is the design of the basic accept or reject user actions. Apparently you swipe left for one and right for the other and users are getting confused. They either forget which is which (I&#39;m sure there are some visual cues so assume they must be going very fast), or they try to go back to a previous one and reject them (I guess that swipe left is probably reject then?).&lt;/p&gt;
&lt;p&gt;My immediate thought was why not make the left and right swipe simply the means of navigating between photos and make swiping up and down the reject and accept actions? It seems more logical to me that a swipe up is pushing the photo away - reject - and that a swipe down is pulling it towards you - accept.&lt;/p&gt;
&lt;p&gt;There you go. In my head I&#39;ve redesigned the UX for an App I&#39;ve never seen.&lt;/p&gt;
</description>
      <pubDate>Thu, 26 Nov 2015 23:16:38 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2015/questioning-the-ux-of-an-app-ive-never-seen/</guid>
    </item>
    <item>
      <title>Forgotten Passwords</title>
      <link>https://chrissmith.xyz/blog/2015/forgotten-passwords/</link>
      <description>&lt;p&gt;Forgotten Your Password? Yes. Yes, I have forgotten my password. Yes, again.&lt;/p&gt;
&lt;p&gt;I always forget my passwords and have to click the forgotten your password link. I resent the wording of “forgotten your password?” as it implies that I’m the one at fault. Gimme a break! The truth of the matter is that as a website user I can’t win. If I pick a nice simple combination of letters and maybe numbers that I can remember easily I’m told that it’s not secure enough; if I pick something suitably complicated or random then I can’t remember it, especially when I’m not supposed to use the same password across multiple sites.&lt;/p&gt;
&lt;p&gt;We want our accounts to be secure and, at the same time, we want the convenience of not having to jump through a multitude of hoops just to log in.&lt;/p&gt;
&lt;p&gt;In reality, the option of picking a simple, memorable password isn’t even an option any more. Your password now has to contain at least one uppercase letter, one lowercase letter, a number and a symbol. How long before you have to type it in blindfolded while standing on one leg?&lt;/p&gt;
&lt;p&gt;So, what actually happens, every time, is that I have 3 or 4 attempts to guess what password I might have used before having to click the forgotten password link. This goes to a new screen which asks me for my email address, again, even though I’ve just tried it several times. I then wait for an email to arrive before clicking a link in the message to back to a screen where I can reset my password. I type in some new soon to be forgotten combination and I’m finally in, usually about 5 minutes after I started. Several times I’ve either run out of time or decided what ever I wanted to do just isn’t worth the hassle.&lt;/p&gt;
&lt;p&gt;Some very secure systems make you change your password every month. Oh thanks. Yeah, that’s helping. And don’t even think about going back to a password you’ve used before. Does anyone really change their password properly each month or do they just increment one digit making it really easy to guess from one month to the next?&lt;/p&gt;
&lt;h3&gt;Keys?&lt;/h3&gt;
Entering a password is fundamentally just me proving my identity by giving a piece of information, a combination of letters, numbers and symbols that nobody else could know. I have something unique which grants me access.
&lt;p&gt;In other parts of life we approach gaining access differently. We secure our precious homes using a physical key. We actually put a piece of metal into a door and turn it, as we have for centuries. It seems quite crude for the 21st century but it’s simple and it works. We can spend our money by using a physical card and entering a four digit PIN. The PIN is easy to remember - it’s only four digits and you can keep the same digits for years. It’s the combination of something physical and a very simple password which makes it secure and easy.&lt;/p&gt;
&lt;p&gt;Why’ve we made gaining online access to things so different? I’m not saying we should all have keys for our devices but an element of the physical could certainly come into play. If our web devices had the ability to read from something physical then we could use the same approach. Hackers would not be able to replicate the physical aspect quickly enough to make it viable to hack.&lt;/p&gt;
&lt;h3&gt;Partial Solutions&lt;/h3&gt;
So, what’s the answer? There is software which will remember passwords for you. Most decent web browsers offer to remember passwords and there are other programs or apps which will allow you access your password list once you enter a master password. The problem with these is that they’re specific to one device and that’s just not necessarily how we do things now. During a typical day I’ll use a work desktop PC, a laptop, a phone and a tablet and I may want to access the same info from any of them.
&lt;p&gt;The closest I’ve seen to an automated solution is to use the same browser across all devices, assuming this is possible, and allow it to remember and sync passwords. Chrome and Firefox offer this. As far as I know the passwords are not stored in the cloud but actually within the browser on each device. My worry is that a site or app could try to imitate the sync process and steal all your password data. I’m sure it’s pretty secure but anything that stores passwords is going to get the attention of hackers.&lt;/p&gt;
&lt;p&gt;How about writing down all your passwords in a notebook? Sounds stupid at first but as there aren’t hoards of bad guys actively trying to steal it it’s probably one of the safer options. The difficulty is keeping it with you and never losing it. It could fall into the wrong hands and easily expose you to problems from people not clever enough to be hackers.&lt;/p&gt;
&lt;p&gt;I think the key to balancing security and convenience is to weigh up how secure access to a site needs to be and how often you use it. Think “if someone got in what’s the worst they could they do?”. With the convenient “forgotten your password” service provided by most sites, if someone has your email address and password they can actually get into pretty much everything.&lt;/p&gt;
&lt;h3&gt;Guard your Email&lt;/h3&gt;
Treat your email address as top priority. Choose a horrible, hard to remember password and make the effort to learn it. Don’t use this password for anything else. If you log into the email provider’s site or app, don’t let your browser or device remember the password - make the effort to type it in each time.
&lt;h3&gt;Get Creative with your Passwords&lt;/h3&gt;
Finally, some fun things you can do to make seemingly random combinations more memorable. None of this is particularly new and won’t fool any serious hackers but it might help meet the increasingly tough password requirements for day to day stuff.
&lt;h3&gt;Use numbers and symbols as letters&lt;/h3&gt;
E99$he11 (eggshell)
£1ephan+ (elephant)
+or+o!5e (tortoise)
D@r+hV@der (DarthVader)
</description>
      <pubDate>Fri, 10 Apr 2015 16:18:48 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2015/forgotten-passwords/</guid>
    </item>
    <item>
      <title>What I Learned in 2014: Part 3 - The Best of the Rest</title>
      <link>https://chrissmith.xyz/blog/2014/what-i-learned-in-2014-part-3/</link>
      <description>&lt;p&gt;This is the final part of a three-part article looking back on new things I’ve discovered in 2014. This part is just a round up of all the other bits and pieces not mentioned in the other parts and a bit of a look forward to 2015.&lt;/p&gt;
&lt;h3&gt;Google Analytics&lt;/h3&gt;
I’ve used Analytics for years but haven’t really used it in any depth for the last couple of years. It’s changed. Quite a lot. All in a good way. It can do a lot more now than before. It seems to be moving closer towards the Webmaster Tools and used well can actually help you improve not only the user experience through design but also the performance of your site through the Behaviour &amp;gt; Page Speed data and suggestions.
&lt;h3&gt;ASP.NET MVC&lt;/h3&gt;
I don’t do a lot server side but colleagues of mine have made excellent use of the EditorFor functionality and partial views to create reusable dynamic page components.
&lt;p&gt;My biggest discovery has been Bundling and Minification of JavaScript and CSS assets. It allows you to create bundles of files and then concatenates them into one long file before minifying it and changing the references. This could mean one single request for all JavaScript, which is then cached - much better for performance and page loading times.&lt;/p&gt;
&lt;h3&gt;Responsive Web Design&lt;/h3&gt;
I still feel like I’m quite new to this but have made some good progress this year. I now understand the basics of mobile and viewport sizing and scaling. I’ve also got the hang of media queries for changing font-sizes and positions of elements based on screen width. I’ve kind of taught myself by looking at the code of sites that do it well rather than by using any tutorials. It seems to be a good shortcut for now. There’s definitely a lot more to learn here but I’m pleased how painless it’s been so far.
&lt;h3&gt;Brackets&lt;/h3&gt;
I’ve recently started using Adobe Brackets, which is an open source code editor available from brackets.io. It’s got everything I need, looks good and from the progress I’ve seen in its first few months it’s going to move pretty fast. The thing I love about it is that it’s built in front end technologies - HTML, CSS and JavaScript.
&lt;h2&gt;To Do List for 2015&lt;/h2&gt;
So, now I see how much I’ve learned in the last year it’s time to start thinking about what’s next for 2015.
&lt;p&gt;One obvious area for me is learning more about SVG. It would be nice to reach a point where any graphic that isn’t a photo could be created in CSS or SVG. I’d quite like to move away from icon font libraries in favour of SVGs to reduce a bit of bloat.&lt;/p&gt;
&lt;p&gt;The other big area is responsive web design, in particular responsive images. Sending large images to mobile devices is bad news and should be a quick win on the performance front.&lt;/p&gt;
&lt;p&gt;I’m sure there will be a lot more that crops up in 2015 as I find a need for it and I may even start learning things that haven’t even been created yet.&lt;/p&gt;
&lt;p&gt;I hope I can help others to learn more too in 2015.&lt;/p&gt;
</description>
      <pubDate>Wed, 31 Dec 2014 16:14:31 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2014/what-i-learned-in-2014-part-3/</guid>
    </item>
    <item>
      <title>What I Learned in 2014: Part 2 - Javascript and Google Maps</title>
      <link>https://chrissmith.xyz/blog/2014/what-i-learned-in-2014-part-2/</link>
      <description>&lt;p&gt;This is the second part of a three-part article looking back at what new web things I’ve learned in 2014. This part focuses on JavaScript.&lt;/p&gt;
&lt;h3&gt;JavaScript and jQuery&lt;/h3&gt;
This is a big area, probably the area where I have made the most progress in the last year. The main shift for me has been from doing everything in jQuery, which I learned first, to using native JavaScript. Hopefully by learning to do more with native Javascript I can cut down on the jQuery bloat, especially in mobile friendly pages.
&lt;p&gt;In “vanilla JavaScript” I’ve learnt to use a few new built-in functions, which perform very well in modern browsers. One of the things that really slows down a page’s performance in JavaScript is looping through a long list of items and performing various operations within each. I’ve learned four new functions which perform operations very quickly - map, filter, forEach and reduce. I would urge anyone using standard for loops to look into these. One for loop operation I tried on a list of 10,000 items killed Chrome. Switching to using map it worked in under a second. I believe that jQuery’s each and filter functions already leverage these bult-in functions. The other useful thing I’ve discovered when working with loops is to move anything you can outside of the loop, e.g. a function. Don’t declare it every time - just do it once and call it each time.&lt;/p&gt;
&lt;p&gt;I’ve finally got the hang of the ternary operator. This just means that I can now write my conditional statements in a much more compact way, things like return (confirmed) ? true : false;. If the variable ‘confirmed’ is truthy, return true, otherwise return false.&lt;/p&gt;
&lt;p&gt;A great discovery in the last couple of months has been the hashchange event. The browser can detect changes to the part of the URL that appears after the #. This means that when we use links to change something like filter the data in a table, instead of the link’s href bring empty or set to the meaningless “#”, we can put something meaningful in there. For example our href could be “#female” and the URL will change to reflect this. The hashchange event will listen for this change and we can then grab the part after the hash symbol using window.location.hash and do our filtering. This has the added bonus of appearing in the browser’s history so the user can hit their back button to undo a filter. Much better and feels like this is how it’s supposed to work.&lt;/p&gt;
&lt;p&gt;I think I’ve now understood how to properly use functions and objects in JavaScript to set the appropriate scope for variables. Wrapping functionality in functions means that each function is its own self-contained unit, which means no unexpected or conflicting references cropping up and it makes the code easier to maintain and test.&lt;/p&gt;
&lt;p&gt;Earlier this year I wrote a jQuery script to handle pagination in a HTML table. I won’t go into the horribly complicated detail here but the learning point for me was to get the logic clear in my mind before getting into the code. I actually went back to pen and paper, sketching out the various scenarios and then finding the patterns to create my code.&lt;/p&gt;
&lt;p&gt;JavaScript Frameworks and jQuery Plugins
Thanks to a very patient colleague I’ve now got a much better grip on Angular.js. I can now work with not just binding data in the HTML but can also write directives to create new page components and services to handle commonly required functions.&lt;/p&gt;
&lt;p&gt;As part of the Angular work I’ve also learned how to do Unit Testing using the Jasmine framework. Unit testing always felt like a lot of extra work to me but now I see that having a long list of small tests that run is invaluable. It gives you the freedom to write new code knowing that any knock-on effects you create in the process will be picked up. It makes for far more robust and less buggy code.&lt;/p&gt;
&lt;p&gt;Recently, I’ve implemented 2 jQuery plugins into a project, tablesorter for automatically sorting the rows of a table by clicking on a column heading, and elevateZoom for adding the capability of zooming in on a thumbnail image, like we often see on clothing details pages. Both are very well written with a lot of options available. Using these has made me realise that I can now go into the code of the plugins and actually follow (more or less) what is going on. I hope to be able to write and share some of my own in the next couple of years.&lt;/p&gt;
&lt;h3&gt;Google Maps API v.3&lt;/h3&gt;
I’ve now spent a few months working with this API and have got a good understanding of how it works and how it can be used and extended to do more. I created my own utility library of functions for all the things I need to do regularly - draw markers and polygons with info windows which appear on click, calculating areas, converting area units, adding data layers and heatmaps, encoding/decoding polygon paths, adding new map controls, etc. There was also some more advanced functionality in there too which goes beyond what’s included in the API - calculating the optimal bounds (map viewport) to show a number of polygons, determining the direction or winding (clockwise or anti/counter-clockwise) of a polygon, calculating the centroid (centre from the average coordinates of points) of a polygon.
&lt;p&gt;I’ve also used some third party features to extend the mapping functionality. One of these has allowed me to cluster markers so rather than have a lot of marekrs close together on screen we show a number of markers, much neater. Another has enabled me to place text labels on the map, which isn’t possible out-of-the-box.&lt;/p&gt;
&lt;p&gt;The key tricks that I have picked up along the way are to 1) push any markers or polygons into an array so you can access them easily in JavaScript and 2) add your own custom properties to the native objects for markers and polygons, e.g. id or name, so that you can identify them easily in code.&lt;/p&gt;
</description>
      <pubDate>Tue, 30 Dec 2014 16:08:26 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2014/what-i-learned-in-2014-part-2/</guid>
    </item>
    <item>
      <title>What I Learned in 2014: Part 1 - HTML, CSS, Fonts and Images</title>
      <link>https://chrissmith.xyz/blog/2014/what-i-learned-in-2014-part-1/</link>
      <description>&lt;p&gt;I thought I’d take a look back through all the new tech that I’ve learnt in 2014. Most of it is genuinely learning new things from scratch but some is polishing up on things I haven’t used for a while or taking things further than I had before. It’s a much longer list than I had expected so I’ve broken it down into 3 articles. Hopefully, it’ll be handy to come back to in the future when I’ve forgotten it all again.&lt;/p&gt;
&lt;h3&gt;HTML&lt;/h3&gt;
I’ve discovered a couple of new things in HTML5. As they’re APIs I uess they’re really Javascript more than HTML. I’ve learned a bit about the Speech API - speech synthesis (turning text content into audio) and speech recognition (turning microphone input into text). It’s still early days and, at the time of writing, only works in Chrome but has some exciting possibilities for both greater accessibility and the ability to use the web without having to look at a page.
&lt;p&gt;My other discovery this year has been the progress element for adding a progress bar to a page. All browsers make these look very different by default but it’s not too hard to style them for consistency if that’s what you want. Like many other HTML5 elements it has nice fallback syntax for non HTML5 browsers.&lt;/p&gt;
&lt;h3&gt;CSS&lt;/h3&gt;
I’d previously only used transitions for adding a bit of a delay into hover effects but it’s great for changing the size or position or page elements too. It works very nicely combined with transform:rotate. I’ve actually found a great practical use for transitions in creating a multi-state button, which changes from displaying “Save” to “Saving…” and then “Saved” with different styling for each state.
&lt;p&gt;I’ve now learned how to do proper keyframe animations in CSS without the need for any Javascript. The possibilities are endless. Just need to make sure I’m not chucking them in everywhere for the sake of it.&lt;/p&gt;
&lt;p&gt;It’s been a while since I’ve had to deal with print media styling. I was hoping things would have improved in the last few years but still find it quite tricky. I found myself having to use a lot of !important in my properties to gain control. Maybe considering print later in the design process rather than from the outset was a mistake with hindsight?&lt;/p&gt;
&lt;h3&gt;Fonts&lt;/h3&gt;
I’ve started making full use of web fonts, particularly Google Fonts. The basic implementation is very easy, just a link to an external CSS file which loads the font-face, but they’re not always consistent across operating systems and browsers so it takes quite a bit of testing to be sure your chosen font will appear nicely across the board. Working out whether to install additional font variants for bold and italic or whether to just let the browser apply its own faux bold and italic effects is another issue. Given the extra HTTP requests and page weight I’m tending to stick with “web safe” fonts for body text and only use web fonts for headings or elements requiring a bit more styling.
&lt;p&gt;I’ve found that I can actually create my own font variants by playing around with the CSS letter-spacing property, using things like letter-spacing:-1px, on “web safe” fonts.&lt;/p&gt;
&lt;h3&gt;Images&lt;/h3&gt;
I haven’t learned much new with images but have found a couple of handy new techniques. I’ve started using base64 format for smaller images instead of referencing external files. This means putting the file data into a continuous stream of characters in the CSS file instead of using a path another file. This still gets cached as part of the CSS but prevents an additional HTTP request. As base64 format is actually a little bigger in file size than refreencing the image directly it only makes sense for smaller files. For larger files it makes more sense to benefit from the smaller file size at the expense of the extra request. Good CSS editors will also show you a preview of the image as you hover over the base654 code, which is handy as it’s completely unintelligible.
&lt;p&gt;I’ve started using some very basic SVG. It seems fairly straightforward but I’m still not sure about the sizing and scaling. One for next year.&lt;/p&gt;
</description>
      <pubDate>Mon, 29 Dec 2014 16:05:41 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2014/what-i-learned-in-2014-part-1/</guid>
    </item>
    <item>
      <title>If Facebook had a Yawn Button</title>
      <link>https://chrissmith.xyz/blog/2014/if-facebook-had-a-yawn-button/</link>
      <description>&lt;p&gt;At the moment Facebook has 3 ways you can interact with posts: Like, Comment and Share. All three of these do slightly different things but they all contribute towards a post’s popularity score, which determines how likely it is to appear in people’s news streams. It makes a lot of sense for users to be shown content that people like or interact with (comments could be negative) rather than content people are indifferent to. In short, it’s a system designed to reward and promote interesting content.&lt;/p&gt;
&lt;p&gt;Facebook is cleverer than this. It records which other users you interact with most and gives their future posts priority in your stream so you see more from those people you have historically found interesting. Good job Facebook barons!&lt;/p&gt;
&lt;p&gt;I think we need the opposite, a way of penalising and demoting the content that we find boring. The way I imagine it working is having a Yawn link with the other options. The main difference with this one is that it would have to be anonymous. We don’t want people to be offended, cause tension or break up friendships. It’s also not intended as a way of judging the quality of other people’s content - what one person finds interesting might be boring to someone else or maybe it’s an in-joke that they just don’t get. It’s about filtering the right content for the right people.&lt;/p&gt;
&lt;h3&gt;The Problem&lt;/h3&gt;
My issue with Facebook right now is that everyone just broadcasts everything to everyone, nothing is targeted. When you write a post you have the option to decide who sees it. You can select individuals, exclude individuals or set up your friends in groups and choose which see it and which don’t. But nobody does. It’s very odd. Think of the last thing you posted on Facebook. Imagine taking that content and putting it into an email and sending it to everyone in your address book. You wouldn&#39;t. I&#39;m sure even though most outgoing people would maybe untick one or two contacts. And this all means that we end up reading lots of content that really isn&#39;t ever meant for us. And the whole Facebook experience becomes irrelevant and ultimately boring.
&lt;h3&gt;The Solution&lt;/h3&gt;
If I post something and it gets 1 Like but 20 Yawns it’ll make me think twice about posting something like that again. But I thought everyone was into learning JavaScript frameworks? I guess you’re all just weirdos. :) What it will do is, the next time I&#39;m enthusiastic about some nerdy tech thing, it’ll make me think about who might be interested and I&#39;ll share it just with them. In this particular case, there’s a fair chance it’ll be nobody but that’s fine.
</description>
      <pubDate>Sun, 28 Sep 2014 15:57:25 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2014/if-facebook-had-a-yawn-button/</guid>
    </item>
    <item>
      <title>My New Website</title>
      <link>https://chrissmith.xyz/blog/2014/my-new-website/</link>
      <description>&lt;p&gt;After years of working on all sorts of websites I thought I’d create my own personal site. I’ve created quite a few sites for myself before but they have always been about my web design and development work or (failed) entrepreneurial attemps to generate a bit of money. This is different. I’m not looking to gain any money, work or reputation, just giving myself a platform to publish, well, whatever the hell I feel like.&lt;/p&gt;
&lt;p&gt;I’m not sure what will go on it yet, maybe a bit of a blog, maybe some articles, photos, video, music. Or I might just fill pages with adverts and animated GIFs. Seems to work for some people.&lt;/p&gt;
&lt;h3&gt;The Design&lt;/h3&gt;
I thought I’d just share some of the thinking and technical approach behind the design. As a web designer/developer I don’t want the site to be just about its content, I see it as a bit of a playground for trying out new design ideas.
&lt;p&gt;To begin with I’ve focused on keeping the design as clean, clear and simple as possible. It’s fully responsive so works on devices of all shapes and sizes. I’ve also kept the technology involved to a minimum serving up static HTML files for maximum speed.&lt;/p&gt;
&lt;p&gt;Going forwards I’m sure I’ll play around with different design ideas so not all pages will look the same. We’ll see what happens.&lt;/p&gt;
&lt;p&gt;Anyway, enough. Hope you enjoy. Now go and do something more useful.&lt;/p&gt;
</description>
      <pubDate>Sun, 07 Sep 2014 07:34:05 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2014/my-new-website/</guid>
    </item>
    <item>
      <title>How to choose the right web host</title>
      <link>https://chrissmith.xyz/blog/2011/how-to-choose-the-right-web-host/</link>
      <description>&lt;p&gt;If you&#39;re starting a new site, it&#39;s very hard to know how to pick the right web host. Which company should you host your site with? How much should you be spending?&lt;/p&gt;
&lt;p&gt;There are a number of factors to consider.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Disk Space
&lt;/strong&gt;This is the actual physical space on the server for your files. If you&#39;re just using text, screen resolution photos and a few icons and graphics then you really won&#39;t need much space at all. A few megabytes will do. If you&#39;re going to be working with high resolution photos, audio or video files then you might need more.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Data Transfer
&lt;/strong&gt;This is the amount of data that is downloaded each month. It&#39;s a combination of the sizes of files on the site and the number of visitors. If your site is well optimised and you&#39;ve kept your files as small as can be then, again, you probably won&#39;t need much data transfer. With a new site things are usually slow to start of with but then snowball as the site grows. YOu need to keep an eye on the monthly data transfer (your web host should give you this) and upgrade to a higher transfer limit only when you need to.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Reliability&lt;/strong&gt;
Many web hosts talk about their &amp;quot;uptime&amp;quot; - the proportion of time that your site will be up. It&#39;s usually 99.9% or higher. With greater reliability comes a higher price tag. YOu have to ask yourself if your site going offline for a short time is really such a bad thing and what it would cost you. Obviously, if you&#39;re a massive site like Amazon then being offline for even a minute could cost you thousands but, in reality, for many new sites it&#39;s probably better to risk a few minor outages and save money on the hosting.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Support&lt;/strong&gt;
Finally, it&#39;s worth weighing up what kind of support you will receive. If you&#39;re new to working with web hosting, managing email accounts or have specialist requirements, e.g. working with ASP.NET, then knowing that there&#39;s someone there to help you can be valuable.&lt;/p&gt;
&lt;p&gt;With a new website my advice would be to start small and let the hosting grow with the site. As the numbers of visitors increases you can naturally afford to invest more in your hosting. Only pay for what you need. Start with a small hosting package on a shared server and upgrade as you need to.&lt;/p&gt;
</description>
      <pubDate>Wed, 19 Jan 2011 17:32:31 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2011/how-to-choose-the-right-web-host/</guid>
    </item>
    <item>
      <title>How to pick the right domain name</title>
      <link>https://chrissmith.xyz/blog/2010/how-to-pick-the-right-domain-name/</link>
      <description>&lt;p&gt;How should you go about selecting the right domain name for your business?&lt;/p&gt;
&lt;p&gt;Firstly, you need to find the &lt;a href=&quot;https://www.hostingobserver.com/free-domain-names.php&quot; target=&quot;_blank&quot;&gt;free domain names&lt;/a&gt; available on the web. For this, you can take help of your web host. Some &lt;a href=&quot;https://www.hostingobserver.com/&quot; target=&quot;_blank&quot;&gt;web hosting plans&lt;/a&gt; include a free domain name with their hosting plan.&lt;/p&gt;
&lt;p&gt;So, once you know where to actually register a name, how do you pick the right one?&lt;/p&gt;
&lt;p&gt;To help demonstrate some different selection methods I&#39;ll use the ficticious example of P J Morris, a long established bookshop based in Ashford, Kent.*&lt;/p&gt;
&lt;p&gt;In an ideal world where all possible domain names are available here are a few different ways of approaching it.&lt;/p&gt;
&lt;p&gt;Firstly, you can just use the business name. Examples:&lt;/p&gt;
&lt;p&gt;pjmorris.co.uk
p-j-morris.co.uk&lt;/p&gt;
&lt;p&gt;This works well if your brand is already known to your audience. People in the town who already know the shop would recognise it online and easily remember the domain name.&lt;/p&gt;
&lt;p&gt;If you&#39;re looking to build a brand or attract visitors who are not familiar with your business, the domain would need to be very simple and memorable.&lt;/p&gt;
&lt;p&gt;Some websites use abstract names, which don&#39;t actually describe what the site has to offer, but they are very easy to remember, easy to spell and very brandable. Some examples of this might be Bing.com and Amazon.com.&lt;/p&gt;
&lt;p&gt;Another approach might be to use the business&#39;s activity as the main focus. Examples:&lt;/p&gt;
&lt;p&gt;books.co.uk
bookshop.co.uk&lt;/p&gt;
&lt;p&gt;(remember we&#39;re assuming that everything&#39;s available)&lt;/p&gt;
&lt;p&gt;These two approaches can, of course, be combined to give the business&#39;s name and its activity. Examples:&lt;/p&gt;
&lt;p&gt;pjmorrisbooks.co.uk
pjmorris-bookshop.co.uk&lt;/p&gt;
&lt;p&gt;Finally, you can use the business location in the domain name, either with the business name, the business activity or both. Examples:&lt;/p&gt;
&lt;p&gt;pjmorrisashford.co.uk
pjmorriskent.co.uk
books-ashford.co.uk
kentbooks.co.uk
pjmorrisbooksashford.co.uk
pjmorris-books-ashford.co.uk&lt;/p&gt;
&lt;p&gt;Using the business location may help match local searches but may also limit your business&#39;s scope to local searchers.&lt;/p&gt;
&lt;p&gt;In the real world, a new site for a book shop would have an enormous amount of competition so combining the name or activity with a geographical reference to successfully match more specific searches is probably a good strategy.&lt;/p&gt;
&lt;p&gt;Some general tips:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;It&#39;s better to avoid using hyphens (-) if possible as people don&#39;t remember them.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
	&lt;li&gt;Try to keep domain names short. pjmorris.co.uk is easy to remember, talk about, give out over the phone and easy to include in any offline marketing, whereas, the other extreme, pjmorris-books-ashford.co.uk, becomes a bit of a mouthful and hard to use.&lt;/li&gt;
&lt;/ul&gt;
* Any resemblance to any real person or business of this name is purely coincidental.
</description>
      <pubDate>Tue, 22 Jun 2010 16:30:45 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2010/how-to-pick-the-right-domain-name/</guid>
    </item>
    <item>
      <title>Static Website or Content Management System?</title>
      <link>https://chrissmith.xyz/blog/2010/static-website-or-content-management-system/</link>
      <description>&lt;p&gt;If you&#39;ve decided you want a website, the next decision to be made is which kind - a simple, static website or a Content Management System (CMS)? Let&#39;s have a look at the pros and cons of each kind.&lt;/p&gt;
&lt;h2&gt;Static website&lt;/h2&gt;
&lt;strong&gt;Pros&lt;/strong&gt;
&lt;ul&gt;
	&lt;li&gt;As it&#39;s simpler it&#39;s quicker. I can produce a static site in a matter of days at a push.&lt;/li&gt;
	&lt;li&gt;When it comes to design, there are no restrictions.&lt;/li&gt;
	&lt;li&gt;It&#39;s cheaper. Cheaper to initially build and cheaper to run.&lt;/li&gt;
&lt;/ul&gt;
&lt;strong&gt;Cons&lt;/strong&gt;
&lt;ul&gt;
	&lt;li&gt;If you want to update it you have to contact the web developer and wait for him/her to update the content for you.&lt;/li&gt;
	&lt;li&gt;If you want to use an XML sitemap you have to have it updated manually each time you change your content.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Content Management System&lt;/h2&gt;
&lt;strong&gt;Pros&lt;/strong&gt;
&lt;ul&gt;
	&lt;li&gt;You can update the site&#39;s content whenever you want, from wherever you want, provided you&#39;ve got an internet connection.&lt;/li&gt;
	&lt;li&gt;It&#39;s even possible to update your website by email.&lt;/li&gt;
	&lt;li&gt;As the site structure is dynamic all navigatoin is handled for you. For example, if you add a new page it automatically appears on the menus.&lt;/li&gt;
	&lt;li&gt;Your XML sitemap is automatically updated every time you change the site&#39;s content, meaning the search engines can keep up you.&lt;/li&gt;
&lt;/ul&gt;
&lt;strong&gt;Cons&lt;/strong&gt;
&lt;ul&gt;
	&lt;li&gt;It&#39;s more expensive. The set up takes longer and the web hosting costs more.&lt;/li&gt;
	&lt;li&gt;The web designer doesn&#39;t have quite as much creative freedom as he&#39;she has to fit in with the CMS framework.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In the end it boils down to how much content you are dealing with and how frequently that content is going to change.&lt;/p&gt;
&lt;p&gt;If you are starting up a new business it may be worth taking advantage of the tax breaks allowed as start-up costs and go for the CMS.&lt;/p&gt;
</description>
      <pubDate>Wed, 02 Jun 2010 16:52:29 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2010/static-website-or-content-management-system/</guid>
    </item>
    <item>
      <title>Good web design – following conventions</title>
      <link>https://chrissmith.xyz/blog/2009/good-web-design-following-conventions/</link>
      <description>&lt;p&gt;When designing a website an important consideration is its usability and, in particular, the site&#39;s visitors being able to understand how to use the site instantly without having to think about it. It should be obvious where to find the login link, the search box, know which text is hyperlinked without having to hover over it, etc.&lt;/p&gt;
&lt;p&gt;The easiest way to design for people is to give them more of what they already know and understand. Let&#39;s take a look at the most popular sites in the UK and see how they do things. We&#39;ll look at where various page elements are positioned and how links are styled. This list comes from &lt;a title=&quot;alexa.com&quot; href=&quot;https://www.alexa.com/topsites/countries/GB&quot; target=&quot;_blank&quot;&gt;Alexa&#39;s Top Sites in the United Kingdom&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Google (UK/Global)&lt;/strong&gt;
&lt;a title=&quot;google.co.uk&quot; href=&quot;https://google.co.uk/&quot; target=&quot;_blank&quot;&gt; google.co.uk&lt;/a&gt;/&lt;a title=&quot;google.com&quot; href=&quot;https://google.com/&quot; target=&quot;_blank&quot;&gt;google.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;logo position - centered, top
login position - top right
search box position - central
settings position - top right
filters/options position - top
ads/sponsored results position - right column
corporate info position - footer
links - blue, underlined
unlinked URLs - green&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Facebook&lt;/strong&gt;
&lt;a title=&quot;facebook.com&quot; href=&quot;https://facebook.com/&quot; target=&quot;_blank&quot;&gt; facebook.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;logo position - top left
login/logout position - top right
search position - top right
options position - top
feed filters position - left column
ads position - right column
corporate info position - footer
post box position - central, top
links - dark blue, not underlined&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;YouTube&lt;/strong&gt;
&lt;a title=&quot;youtube.com&quot; href=&quot;https://youtube.com/&quot; target=&quot;_blank&quot;&gt; youtube.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;logo position - top left
login position - top right
search box position - top, central and repeated at foot of page
corporate info position - footer
links - blue, not underlined&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Yahoo!&lt;/strong&gt;
&lt;a title=&quot;yahoo.com&quot; href=&quot;https://yahoo.com/&quot; target=&quot;_blank&quot;&gt; yahoo.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;logo position - top left
login position - top right
search box position - top, central
filters position - top
options/filters/personalised links position - left column
corporate info position - footer
links - dark blue, not underlined
links - black, not underlined (in menu box)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bing&lt;/strong&gt;
&lt;a title=&quot;bing.com&quot; href=&quot;https://bing.com/&quot; target=&quot;_blank&quot;&gt;bing.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;logo position - top left
login position - top right
search box position - central, top
corporate info position - footer
links - white, not underlined (to fit with background image)
links - blue, underlined
links - blue, not underlined (in menu box)
unlinked URLs - green&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;BBC&lt;/strong&gt;
&lt;a title=&quot;bbc.co.uk&quot; href=&quot;https://bbc.co.uk/&quot; target=&quot;_blank&quot;&gt; bbc.co.uk&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;accessibility info position - top left
logo position - top left
search box position - top, central
corporate info position - footer
links - green, not underlined&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;eBay UK&lt;/strong&gt;
&lt;a title=&quot;ebay.co.uk&quot; href=&quot;https://ebay.co.uk/&quot; target=&quot;_blank&quot;&gt; ebay.co.uk&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;logo position - top left
login position - top
search box position - top
filters position - left column
corporate info position - footer
links - blue, not underlined&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The consensus&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;From looking at these popular sites we can see these common conventions:&lt;/p&gt;
&lt;p&gt;logo position - usually top left corner
login position - usually top right corner
search box position - always at the top, usually central
corporate info position - always found in the page&#39;s footer
search filters or options position - either running horizontally across the top or down the left side
ads position - in the right column, after the main content
links - usually blue or dark blue, sometimes underlined, more commonly not but underlined on hover&lt;/p&gt;
&lt;p&gt;Consciously or not, this is what people are used to seeing on the web so this is what you should follow. Web users will instinctively look for these page elements in these locations and understand links in these colour schemes. Any deviation from &amp;quot;the norm&amp;quot; will increase the chances of uncertainty or confusion.&lt;/p&gt;
</description>
      <pubDate>Wed, 16 Sep 2009 14:25:03 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2009/good-web-design-following-conventions/</guid>
    </item>
    <item>
      <title>Fighting Spam</title>
      <link>https://chrissmith.xyz/blog/2009/fighting-spam/</link>
      <description>&lt;p&gt;Junk email and blog posts are a constant problem. Here are a few ways to help spoil the spammers&#39; fun.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Email Spam&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;There are a lot of anti-spam or spam filter products around these days, many included in mail software but the sad fact is that once you&#39;re getting spam you&#39;re likely to keep getting spam regardless of these filters.&lt;/p&gt;
&lt;p&gt;Spammers are able to change the sender&#39;s email address, subject and body of an email so easily that if you block them they can still mail you just using a different mail account.&lt;/p&gt;
&lt;p&gt;Anti-spam software like anti-virus software can only deal with what it knows to be harmful or unwanted. Anything new or unknown will slip through the net.&lt;/p&gt;
&lt;p&gt;The way to avoid spam is never to let your email address get into the wrong hands. Once a spammer has got your email address they can not only use it to send you junk email but also sell it on to other spammers. Once you&#39;re address is out there you&#39;ve no hope of keeping the spam at bay.&lt;/p&gt;
&lt;p&gt;If we understand how the spammers get our email addresses we can avoid them.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Unscrupulous Websites
&lt;/strong&gt;
This is an obvious one but when giving your email address as part of registration on a website be careful to check the terms and conditions or privacy policy as you may be agreeing to have your details passed to a third party. You just have to judge carefully how trustworthy you think the site is.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Unwanted Newsletters&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;At times it can be risky signing up to newsletters by email. Even though they offer you the option to unsubscribe at ay time they may also subscribe you to other similar newsletters without your express permission. You might sign up to receive newsletters from one site and start receiving them from another related site. Often where companies own several websites with subscription services they can try to cross-promote. Check the terms and conditions or privacy policy carefully.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Harvesting Web Pages&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is a common process used to gather email addresses. Robots trawl through websites looking for email addresses and feeding them back to the spammer. In short, never give an email address on a web page. Instead use a contact form which delivers the message to your inbox without ever revealing the address.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Guessing Common Recipient Names&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Many spammers will not even try to find email addresses but will just try their luck at guessing them. If they know the domain name and send emails to info@ or sales@ there&#39;s a good chance some of them will get through. If you try to use email addresses that are less obvious you shouldn&#39;t get as much spam.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Email Scams&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;At one time or another you&#39;ve probably had an email from a friend or colleague with some &amp;quot;too good to be true&amp;quot; offer or superstitious nonsense. These scams are easy to spot as they usually ask you to forward the message to a certain number of people and CC a particular email address.&lt;/p&gt;
&lt;p&gt;The offers are never real. What is actually happeneing is the spammers are relying on people&#39;s naivety to spread the email. Each time the email is forwarded to 10 people the spammer will get an email back (the CC address) and have 10 new email addresses to add to his/her spam database.&lt;/p&gt;
&lt;p&gt;The difficulty with this is that to a certain degree it&#39;s beyond your control. You just need to make sure that you&#39;re never taken in by these scams and do your best to make your friends and colleagues aware of this scamming technique so that you don&#39;t appear on their forwarding list.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Forms and Blogs&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Contact forms, blogs and other Web 2.0 applications invite visitors to a webpage to leave comments or provide feedback. Spammers see this a an opportunity to leave spam messages usually containing links to their websites.&lt;/p&gt;
&lt;p&gt;Comments can often be set so that they have to be moderated and manually approved by the owner before being published but even then huge amounts of spam can become a problem with moderation becoming unmanageable.&lt;/p&gt;
&lt;p&gt;There are two answers to this - use clever scripting to fool spam robots or use a &lt;a title=&quot;captcha&quot; href=&quot;https://www.recaptcha.net/&quot; target=&quot;_blank&quot;&gt;CAPTCHA&lt;/a&gt; control in your page.&lt;/p&gt;
&lt;p&gt;Spam robots visit pages and look for opportunities to enter content. They cannot do things that a human user can do such as answer questions or interpret images. By forcing the page visitor to act like a human in order to leave a message we can reduce spam to only that manually left by real people.&lt;/p&gt;
&lt;p&gt;Spam robots can easily be fooled by using fake fields in a form. Include a field for some bit of information you don&#39;t actually need and hide it using CSS. Only allow the message to be left if the field is blank. The spam robot will complete it.&lt;/p&gt;
&lt;p&gt;You&#39;ve probably come across &lt;a title=&quot;captcha&quot; href=&quot;https://www.recaptcha.net/&quot; target=&quot;_blank&quot;&gt;CAPTCHA&lt;/a&gt; controls but may not know them by this name. You&#39;re shown a fuzzy image containing a word or letters and numbers and then asked to type the characters into a text field. Spam robots can&#39;t do this.&lt;/p&gt;
&lt;p&gt;If you&#39;re having problems with spam coming from your website ask your web developer to use some of these measures and you should see a difference within a short time.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;6 Quick Tips
&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Never open spam emails - if in doubt, delete it&lt;/li&gt;
&lt;li&gt;Never reply to spam emails - you&#39;re just confirming delivery&lt;/li&gt;
&lt;li&gt;Never forward suspicious emails - don&#39;t spread the problem&lt;/li&gt;
&lt;li&gt;Check terms or privacy policy when giving your email address&lt;/li&gt;
&lt;li&gt;Never publish an email address on a web page&lt;/li&gt;
&lt;li&gt;Use scripting or a CAPTCHA control on web forms - don&#39;t allow spam robots to post&lt;/li&gt;
&lt;/ol&gt;
</description>
      <pubDate>Mon, 14 Sep 2009 12:36:03 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2009/fighting-spam/</guid>
    </item>
    <item>
      <title>Twitter explained simply</title>
      <link>https://chrissmith.xyz/blog/2009/twitter-explained-simply/</link>
      <description>&lt;p&gt;&lt;a title=&quot;Twitter&quot; href=&quot;https://twitter.com/&quot; target=&quot;_blank&quot;&gt;Twitter&lt;/a&gt; keeps hitting the headlines at the moment but a lot of people don&#39;t seem to understand what it really is and how it differs from other Social Networks. I&#39;ll try to explain it in terms more people can understand.&lt;/p&gt;
&lt;p&gt;&lt;a title=&quot;Twitter&quot; href=&quot;https://twitter.com/&quot; target=&quot;_blank&quot;&gt;Twitter&lt;/a&gt; is basically about posting short messages, much like SMS texting on mobiles. Each post is called a &amp;quot;tweet&amp;quot; and is limited to 140 characters. It can&#39;t include other media as such but it can include hyperlinks so anything you wish to share is only a click away.&lt;/p&gt;
&lt;p&gt;It doesn&#39;t work like email where you choose the recipients of your messages but more like a subscription service. You put your message out there and it&#39;s read by your subscribers. In many ways it&#39;s more like broadcasting.&lt;/p&gt;
&lt;p&gt;As a &lt;a title=&quot;Twitter&quot; href=&quot;https://twitter.com/&quot; target=&quot;_blank&quot;&gt;Twitter&lt;/a&gt; user, or &amp;quot;Twitterer&amp;quot;, you have the option to &amp;quot;follow&amp;quot; other users meaning you subscribe to their broadcasts. Each user has lists of &amp;quot;following&amp;quot; - who he/she has chosen to follow and &amp;quot;followers&amp;quot; - who is following him/her.&lt;/p&gt;
&lt;p&gt;&lt;a title=&quot;Twitter&quot; href=&quot;https://twitter.com/&quot; target=&quot;_blank&quot;&gt;Twitter&lt;/a&gt; has 2 real strengths which differentiate it from other networks.&lt;/p&gt;
&lt;p&gt;Firstly, the 140 characters limit means it is highly portable and works well with mobile phone applications. For example, it&#39;s very easy to let your followers know what you&#39;re doing whilst on the move.&lt;/p&gt;
&lt;p&gt;Secondly, when you read someone else&#39;s &amp;quot;tweet&amp;quot; there&#39;s a facility to &amp;quot;retweet&amp;quot; it, which means instantly broadcasting it to all of your followers. This means that something written by one person can reach millions within a very short time frame. This is what tends to happen with big breaking news stories and this is why it is becoming such a powerful tool for &lt;a title=&quot;Internet Marketing&quot; href=&quot;https://www.chrissmithmarketing.com/&quot; target=&quot;_self&quot;&gt;marketing&lt;/a&gt; and PR.&lt;/p&gt;
&lt;p&gt;If anyone wants to follow me and be alerted to new articles I&#39;m &lt;a href=&quot;https://twitter.com/chris22smith&quot; target=&quot;_self&quot;&gt;@chris22smith&lt;/a&gt;.&lt;/p&gt;
</description>
      <pubDate>Fri, 03 Jul 2009 11:37:27 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2009/twitter-explained-simply/</guid>
    </item>
    <item>
      <title>Web traffic through quality links</title>
      <link>https://chrissmith.xyz/blog/2009/web-traffic-through-quality-links/</link>
      <description>&lt;p&gt;I&#39;ve recently started a new &lt;a title=&quot;web development blog&quot; href=&quot;https://dinowebs.net/&quot; target=&quot;_self&quot;&gt;web development blog&lt;/a&gt; and have been pleasantly surprised at the high levels of traffic (relative to anything I&#39;ve done before) it&#39;s receiving after such a short space of time. I&#39;ll share with you how I&#39;ve achieved this.&lt;/p&gt;
&lt;p&gt;My &lt;a title=&quot;traffic building strategy&quot; href=&quot;https://www.chrissmithmarketing.com/&quot; target=&quot;_self&quot;&gt;traffic building strategy&lt;/a&gt; was to target a few carefully chosen high quality links. My plan was to try to create a small number of links to my site, quality not quatity, coming from web pages highly ranked by &lt;a title=&quot;Google&quot; href=&quot;https://www.google.co.uk/&quot; target=&quot;_blank&quot;&gt;Google&lt;/a&gt; and with a subject matching the page on my site. I also decided to use deep linking rather than just point everything at my home page.&lt;/p&gt;
&lt;p&gt;The subject of my blog is &lt;a title=&quot;web development resources&quot; href=&quot;https://dinowebs.net/&quot; target=&quot;_self&quot;&gt;web development resources&lt;/a&gt; and, in particular, &lt;a title=&quot;ASP.NET web development&quot; href=&quot;https://dinowebs.net/&quot; target=&quot;_self&quot;&gt;ASP.NET web development&lt;/a&gt;. (Two links in that last sentence, sorry, can&#39;t help myself.)&lt;/p&gt;
&lt;p&gt;When I blogged about a particular solution I then went in search (&lt;a title=&quot;Google&quot; href=&quot;https://www.google.co.uk/&quot; target=&quot;_blank&quot;&gt;Google&lt;/a&gt;) of people with technical issues looking for my solution. All I then did was create a forum account and post a reply linking out to my blog post. Highly relevant. I&#39;d respond to forum posts that had been dead for 2 years. Doesn&#39;t matter. I&#39;m still getting a link to my site which is good for me and the solution is posted on that forum for anyone who searches in the future.&lt;/p&gt;
&lt;p&gt;The key point is that in this scenario is that the inbound links I have created are actually useful to the linking site&#39;s audience. Everybody wins. It&#39;s in no way trying to cheat the system. This is the right way to generate your inbound links.&lt;/p&gt;
</description>
      <pubDate>Sun, 21 Jun 2009 22:41:53 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2009/web-traffic-through-quality-links/</guid>
    </item>
    <item>
      <title>Introducing... Dinowebs.net</title>
      <link>https://chrissmith.xyz/blog/2009/introducing-dinowebsnet/</link>
      <description>&lt;p&gt;As a web developer and programmer I&#39;m always on the look out for solutions to little problems. How do I do that? How can I make that do this without X, Y and Z happening? You get the idea.&lt;/p&gt;
&lt;p&gt;My first port of call is always &lt;a title=&quot;Google&quot; href=&quot;https://www.google.co.uk/&quot; target=&quot;_blank&quot;&gt;Google&lt;/a&gt;. The way I see it is that I&#39;m unikely to ever have a technical requirement that somebody else hasn&#39;t had before. In fact, it&#39;s highly likely that hundreds, even thousands of people have faced the same challenges. By using the right search terms on &lt;a title=&quot;Google&quot; href=&quot;https://www.google.co.uk/&quot; target=&quot;_blank&quot;&gt;Google&lt;/a&gt; I can usually find the answers to my problems. This inspired me to build a &lt;a title=&quot;technical blog&quot; href=&quot;https://dinowebs.net/&quot; target=&quot;_self&quot;&gt;technical blog&lt;/a&gt;. It&#39;s my way of sharing what I&#39;ve learnt and, hopefully, helping someone else out.&lt;/p&gt;
&lt;p&gt;As well as trying to help others it&#39;s also tremendously useful to me. Every time I overcome an obstacle I write about it and provide the solution giving &lt;a title=&quot;code examples&quot; href=&quot;https://dinowebs.net/&quot; target=&quot;_self&quot;&gt;code examples&lt;/a&gt; where I can. It&#39;s very handy to just be able to just come back to it rather than try to remember things that I&#39;ve done in the past. I also use the site for setting up links to &lt;a title=&quot;web development resources&quot; href=&quot;https://dinowebs.net/&quot; target=&quot;_self&quot;&gt;resources&lt;/a&gt; I like and use. Again, it just saves me time looking for things.&lt;/p&gt;
&lt;p&gt;My site is called &lt;a title=&quot;Dinowebs&quot; href=&quot;https://dinowebs.net/&quot; target=&quot;_self&quot;&gt;Dinowebs&lt;/a&gt;, &lt;a title=&quot;Dinowebs&quot; href=&quot;https://dinowebs.net/&quot;&gt;https://dinowebs.net&lt;/a&gt;. The site covers all sorts of &lt;a title=&quot;coding&quot; href=&quot;https://dinowebs.net/&quot; target=&quot;_self&quot;&gt;coding&lt;/a&gt; and &lt;a title=&quot;web development&quot; href=&quot;https://dinowebs.net/&quot; target=&quot;_self&quot;&gt;web development&lt;/a&gt; subject matter. Please take a look.&lt;/p&gt;
</description>
      <pubDate>Sun, 21 Jun 2009 22:21:47 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2009/introducing-dinowebsnet/</guid>
    </item>
    <item>
      <title>My website is 5 today!</title>
      <link>https://chrissmith.xyz/blog/2009/my-website-is-5-today/</link>
      <description>&lt;p&gt;My website, www.chris-smith-web.com, is 5 years old today.&lt;/p&gt;
&lt;p&gt;I registered the domain name and started building the site on 15th June 2004. This has made me all nostalgic so I thought I&#39;d take a quick look back over the last 5 years and how the site and business has changed in that time.&lt;/p&gt;
&lt;p&gt;I registered the domain with a company called &lt;a title=&quot;123 Reg&quot; href=&quot;https://www.123-reg.co.uk/&quot; target=&quot;_blank&quot;&gt;123-reg&lt;/a&gt; whom I still use to this day. They provide good value domain registration with a nice simple control panel. I also hosted my first site with them though now I have moved on, mainly due to the more advanced technologies I now use.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2004&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;My first design was fairly basic but, looking back on it now, I still like its simplicity and clarity.&lt;/p&gt;
&lt;p&gt;Although it was a new site it managed to bring in some good enquiries and before long I was off and running.&lt;/p&gt;
&lt;p&gt;I can still remember my first enquiry and the first website I built for a client very clearly.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2006&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;As the &amp;quot;cheap web design&amp;quot; market got more and more competitive I needed to redesign the site to try to improve its search engine rankings. I tried using an individual web page for each individual service I could offer.&lt;/p&gt;
&lt;p&gt;With hindsight, I think what I gained in web traffic I lost in conversions as this design failed to impress web development seekers.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2007&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Another year on the web was changing and Web 2.0 technologies were becoming more common. I decided I needed a different design with a fresher, more vibrant feel. This design change saw a marked improvement in my enquiry levels.&lt;/p&gt;
&lt;p&gt;I also started using server side technology to create more interactivity.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Today&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;My site now uses a blogging model and has articles as its centre rather than just the static pages about my services. This model is strong on the search engine side and my visitor numbers are higher than ever. It also means I get to write about the things that I&#39;m passionate about - web development and online marketing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Future&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I&#39;m just in the process of launching a new site focused on Online Marketing. Please take a look at Chris Smith Marketing, www.chrissmithmarketing.com.&lt;/p&gt;
</description>
      <pubDate>Mon, 15 Jun 2009 09:42:36 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2009/my-website-is-5-today/</guid>
    </item>
    <item>
      <title>Monitoring your Marketing with Unique URLs</title>
      <link>https://chrissmith.xyz/blog/2009/monitoring-your-marketing-with-unique-urls/</link>
      <description>&lt;p&gt;Using &lt;a title=&quot;Google Analytics&quot; href=&quot;https://www.google.com/analytics&quot; target=&quot;_blank&quot;&gt;Google Analytics&lt;/a&gt; or a similar web stats package you can see how many people are visiting a particular page or downloading a particular document on your website.&lt;/p&gt;
&lt;p&gt;When you&#39;re creating a new online marketing campaign it&#39;s useful for you to be clear on what web traffic has been generated from a specific activity rather than just look at your overall traffic.&lt;/p&gt;
&lt;p&gt;For example, if you were promoting a particular event you might place a link on your website&#39;s home page, run an ad on &lt;a title=&quot;Facebook&quot; href=&quot;https://www.facebook.com/&quot; target=&quot;_blank&quot;&gt;Facebook&lt;/a&gt; and do an email to your contacts. It would be very useful to know the effectiveness of each of these activities.&lt;/p&gt;
&lt;p&gt;The easiest way to monitor this is to use specific URLs, one for each activity or source.&lt;/p&gt;
&lt;p&gt;Instead of adding a normal link to your page, e.g. &lt;span style=&quot;color: #800000&quot;&gt;https://www.yourwebsite.com/event.htm&lt;/span&gt;, you can create unique URLs by adding additional information on to the end of the URL. These additional bits of information are called parameters and values. Here are some examples:&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #800000&quot;&gt;https://www.yourwebsite.com/event.htm?src=homepage
https://www.yourwebsite.com/event.htm?src=facebook
https://www.yourwebsite.com/event.htm?src=email&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;To introduce additional information you add a question mark &amp;quot;?&amp;quot; to the end and then a parameter name. This can be anything you like. Here I&#39;ve used &amp;quot;src&amp;quot; short for source. You then have an equals sign &amp;quot;=&amp;quot; and set a value against it. Again, this can be anything you like.&lt;/p&gt;
&lt;p&gt;If you&#39;re website is database driven your URLs may already have one or more sets of parameters and values in the URL (look for a question mark). If this is the case you simply need to add an ampersand &amp;quot;&amp;amp;&amp;quot; on to the end plus your parameter name, an equals sign &amp;quot;=&amp;quot; and a value. The ampersand is used to join pairs of parameters and values.&lt;/p&gt;
&lt;p&gt;By adding further sets of parameters and values to the URL you can get more detailed information back. For example, if your contacts database identified people&#39;s sex and you wanted to check whether more men or women were visiting your page you could use the URLs:&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #800000&quot;&gt;https://www.yourwebsite.com/event.htm?src=email&amp;amp;sex=male
https://www.yourwebsite.com/event.htm?src=email&amp;amp;sex=female&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;You can use this URL monitoring to see which activities are working for you and which are providing the best value for money and return on investment.&lt;/p&gt;
</description>
      <pubDate>Tue, 09 Jun 2009 12:17:25 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2009/monitoring-your-marketing-with-unique-urls/</guid>
    </item>
    <item>
      <title>Don&#39;t put all your eggs in Google&#39;s basket</title>
      <link>https://chrissmith.xyz/blog/2009/dont-put-all-your-eggs-in-googles-basket/</link>
      <description>&lt;p&gt;Working on your website&#39;s search engine optimisation (SEO) is all well and good but it&#39;s a dangerous strategy to use this one source of web traffic in isolation. I&#39;ve found this out the hard way.&lt;/p&gt;
&lt;p&gt;Yes, there&#39;s no disputing that appearing at the top of the &lt;a title=&quot;Google UK&quot; href=&quot;https://www.google.co.uk/&quot; target=&quot;_blank&quot;&gt;Google&lt;/a&gt; search results for the right phrases will bring in visitors but using this as your sole strategy could be very risky. You shouldn&#39;t be too dependent on &lt;a title=&quot;Google UK&quot; href=&quot;https://www.google.co.uk/&quot; target=&quot;_blank&quot;&gt;Google&lt;/a&gt; as things can change very quickly.&lt;/p&gt;
&lt;p&gt;I&#39;ve experienced it myself a number of times. I&#39;ve had my site sitting pretty in the top 5 results only for it to suddenty plummet down to the fourth page or lower or vanish from the search results altogether.&lt;/p&gt;
&lt;p&gt;&lt;a title=&quot;Google UK&quot; href=&quot;https://www.google.co.uk/&quot; target=&quot;_blank&quot;&gt;Google&lt;/a&gt; ranks web pages and other documents by following an algorithm, a complex formula. As they continually try to improve their search technology they tweak this algorithm from time to time. Depending on the change this can have quite dramatic effects on ranking. Through no fault of your own you can suddenly lose your foothold on a particular phrase or market.&lt;/p&gt;
&lt;p&gt;&lt;a title=&quot;Google UK&quot; href=&quot;https://www.google.co.uk/&quot; target=&quot;_blank&quot;&gt;Google&lt;/a&gt; indexes websites by periodically visiting them with it&#39;s search robot, &lt;a title=&quot;Googlebot&quot; href=&quot;https://www.google.com/support/webmasters/bin/answer.py?answer=70897&quot; target=&quot;_blank&quot;&gt;Googlebot&lt;/a&gt;. The frequency of these visits depends on the frequency of your site updates. If you&#39;re unlucky enough for your website to be down at the time when &lt;a title=&quot;Googlebot&quot; href=&quot;https://www.google.com/support/webmasters/bin/answer.py?answer=70897&quot; target=&quot;_blank&quot;&gt;Googlebot&lt;/a&gt; visits you&#39;ll drop out of the index and have to wait until it drops by again before reappearing.&lt;/p&gt;
&lt;p&gt;The other big factor is competition. In competitive markets your competitors will be working tirelessly to try to grab the top spot. Changes they make to their sites or search engine marketing activity can easily leave you playing catch up.&lt;/p&gt;
&lt;p&gt;I&#39;m not suggesting for a second that you should stop pushing for a high ranking on &lt;a title=&quot;Google UK&quot; href=&quot;https://www.google.co.uk/&quot; target=&quot;_blank&quot;&gt;Google&lt;/a&gt; but you should be doing other things too so that should anything change your site doesn&#39;t grind to a halt.&lt;/p&gt;
</description>
      <pubDate>Fri, 05 Jun 2009 16:03:12 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2009/dont-put-all-your-eggs-in-googles-basket/</guid>
    </item>
    <item>
      <title>Hits schmits! What do Web Statistics really mean?</title>
      <link>https://chrissmith.xyz/blog/2009/hits-schmits-what-do-web-statistics-really-mean/</link>
      <description>&lt;p&gt;With web technologies it&#39;s very easy to quote and manipulate the statistics to make things sound better or worse than they actually are. There are some grey areas in the terminology used and it&#39;s very easy to get lost and not understand precisely what you&#39;re being told. Here is a guide to help explain some of the more commonly used terms.&lt;/p&gt;
&lt;p&gt;Back in the nineties everyone would talk about &lt;strong&gt;hits&lt;/strong&gt;, how many hits they were getting, hit counts, they&#39;d even have a little hit counter on their home page.&lt;/p&gt;
&lt;p&gt;So, what is a hit? A hit means a file that is retrieved from the web server. The key thing to note here is that it&#39;s a file, not a page but a file. Therefore, if someone visits a page with 3 image files that&#39;s 4 hits, the HTML file plus the 3 image files. A photo gallery page might have 60 thumbnail images in it - that&#39;s 61 hits. It&#39;s very easy to rack up huge numbers of hits and make it sound like you&#39;re getting far more traffic than you are. This is because a lot of people misunderstand hits to mean visits.&lt;/p&gt;
&lt;p&gt;A &lt;strong&gt;visit&lt;/strong&gt;, sometimes called a &lt;strong&gt;page impression&lt;/strong&gt; or &lt;strong&gt;page view&lt;/strong&gt;, means one retrieval of a web page from the web server. This term is, at least, what it sounds like. Measuring visits does not take into account the same person visiting multiple times. This is an area to be wary of when paying for advertising on a per thousand impressions or CPM basis. You may get 1,000 impressions, views or visits in a month but it could be only 100 real people who access your page 10 times each. Do not mistake visits for visitors.&lt;/p&gt;
&lt;div style=&quot;border:solid 1px #CCCCCC;padding:25px;margin:20px;float:right&quot;&gt;&quot;88.2% of statistics are made up on the spot.&quot;
- Vic Reeves&lt;/div&gt;
A &lt;strong&gt;visitor&lt;/strong&gt; is a real person, most of the time. As well as people your site may be visited by search engine spiders or robots performing information retrieval tasks. These will all count so you need to be aware that what you see is not 100% what you get.
&lt;p&gt;Another term that is used is &lt;strong&gt;unique visits&lt;/strong&gt; and &lt;strong&gt;unique visitors&lt;/strong&gt;. The idea behind labelling them unique is that they are not counted twice. It works either by using cookies or logging IP addresses or often both. It&#39;s not perfect as I can visit the same web page from work and home in the same day and be double counted but it&#39;s as close as can be realistically expected. The danger with the term unique is that it can have different parameters. Some people use the term unique to mean that the visitor is only counted once for the duration being discussed, e.g. per calendar month. Others use the term unique to mean that each visitor is only counted once in every 24 hour period within the duration. So, if I visit your web page every day in June you could get 1 unique visitor or 30. Quite a difference.&lt;/p&gt;
&lt;p&gt;Before buying a website, domain name, advertising space or anything else where stats are quoted at you, be sure to nail down exactly what you&#39;re talking about.&lt;/p&gt;
&lt;p&gt;On the flip side, when trying to sell advertising space, a good solution to overcome any misunderstandings is to use &lt;a title=&quot;Google Analytics&quot; href=&quot;https://www.google.com/analytics/&quot; target=&quot;_blank&quot;&gt;Google Analytics&lt;/a&gt; on your website. This presents visitor data under clear headings in a way which many webmasters or website owners will understand.&lt;/p&gt;
</description>
      <pubDate>Thu, 04 Jun 2009 15:50:45 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2009/hits-schmits-what-do-web-statistics-really-mean/</guid>
    </item>
    <item>
      <title>Need a website? Confused about what you need? Read this.</title>
      <link>https://chrissmith.xyz/blog/2009/need-a-website-confused-about-what-you-need-read-this/</link>
      <description>&lt;p&gt;Here are the real basics of starting a website in simple, jargon-free, easy to understand English.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How a website works&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A website is a collection of files (text, images, video, etc.) on a computer made available to the public. When someone visits a website files are copied to the visitor&#39;s computer for them to view. Each web page needs a unique address so that people can find it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What do you need?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To run a website you need three things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;someone to create the files for you,&lt;/li&gt;
&lt;li&gt;somewhere to make them available and&lt;/li&gt;
&lt;li&gt;a nice name to make it easy to find.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The process of creating these files is known as web development.
The service of making them available is known as web hosting.
The name for a site is known as the domain name.&lt;/p&gt;
&lt;p&gt;These three elements are available as separate services from different suppliers or can often be bought together from one.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Web Development&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You need the services of a web developer or web designer. In real terms when you&#39;re searching for someone to prepare a site for you there&#39;s not much difference between the two but a designer is possibly more concerned with the site&#39;s appearance and style whereas a developer is more focused on how people use the site.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Web Hosting&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To make your site available to the public you need it to be hosted. Web &lt;a href=&quot;https://www.hostingobserver.com/&quot; target=&quot;_blank&quot;&gt;hosting&lt;/a&gt; companies have special computers designed for this purpose called web servers. In order to put your website onto the web server and make changes to it your web developer will need access to your hosting account.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Domain Names&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To give your site a nice user-friendly name you need to register a domain name with a domain name registrar. There are lots of sites that offer this service including a lot of web developers or hosting companies. The domain needs to be set to point visitors to your hosting account. Instructions of how to do this are usually provided by the hosting company or a web developer will do this for you.&lt;/p&gt;
</description>
      <pubDate>Tue, 12 May 2009 12:31:43 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2009/need-a-website-confused-about-what-you-need-read-this/</guid>
    </item>
    <item>
      <title>My Firefox Add-ons</title>
      <link>https://chrissmith.xyz/blog/2009/my-firefox-add-ons/</link>
      <description>&lt;p&gt;I use &lt;a title=&quot;Mozilla Firefox&quot; href=&quot;https://www.mozilla-europe.org/en/firefox/&quot; target=&quot;_blank&quot;&gt;Mozilla Firefox&lt;/a&gt; as my prefered web browser. &lt;a title=&quot;Firefox&quot; href=&quot;https://www.mozilla-europe.org/en/firefox/&quot; target=&quot;_blank&quot;&gt;Firefox&lt;/a&gt; allows you to expand its functionality by adding on mini programs. These are called add-ons. I thought I&#39;d share some of my favourite add-ons.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;AdBlock Plus&lt;/strong&gt;
This add-on blocks adverts in web pages. It collapses any content being imported from ad servers. You should see how small the &lt;a title=&quot;Yahoo!&quot; href=&quot;https://uk.yahoo.com/&quot; target=&quot;_blank&quot;&gt;Yahoo! home page&lt;/a&gt; becomes without its advertising. There are no more sponsored results on search engine pages, only organic results. It allows you to manually create exceptions, pages where ads are allowed. Where it detects any Flash content it displays a tiny button so that you can manually block this content.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Xmarks (formerly Foxmarks)&lt;/strong&gt;
This is a Bookmark or Favourites synchronisation tool. Put simply, if you use more than one computer it keeps your bookmarks or favourites consitent. I use three different PCs and find this tool invaluable.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;TwitterFox&lt;/strong&gt;
If you use &lt;a title=&quot;Twitter&quot; href=&quot;https://www.twitter.com/&quot; target=&quot;_blank&quot;&gt;Twitter&lt;/a&gt; this is very useful. You can stay connected to your &lt;a title=&quot;Twitter&quot; href=&quot;https://www.twitter.com/&quot; target=&quot;_blank&quot;&gt;Twitter&lt;/a&gt; account without the need for having the site open. Any new tweets are popped up in a bubble at the bottom of your browser window. Clicking on the status bar icon allows you to read tweets or tweet yourself quickly and easily.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Facebook Toolbar&lt;/strong&gt;
Similar to the Twitter tool this keeps you up to date with happenings on &lt;a title=&quot;Facebook&quot; href=&quot;https://www.facebook.com/&quot; target=&quot;_blank&quot;&gt;Facebook&lt;/a&gt; via small pop up messages in your web browser. The toolbar allows you to update your status in the browser, see how many items in your inbox, view your friends in a sidebar as well as share the content of the page you are currently browsing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Digg Toolbar&lt;/strong&gt;
This makes it quick and easy to share the content of the page you are browsing on &lt;a title=&quot;Digg&quot; href=&quot;https://digg.com/&quot; target=&quot;_blank&quot;&gt;Digg&lt;/a&gt;. With one click (&amp;quot;Digg This&amp;quot;) you can submit a new URL to &lt;a title=&quot;Digg&quot; href=&quot;https://digg.com/&quot; target=&quot;_blank&quot;&gt;Digg&lt;/a&gt; to share with the online community.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Delicious Toolbar&lt;/strong&gt;
Like &lt;a title=&quot;Digg&quot; href=&quot;https://digg.com/&quot; target=&quot;_blank&quot;&gt;Digg&lt;/a&gt; this allows you to add and share online bookmarks to &lt;a title=&quot;Delicious&quot; href=&quot;https://delicious.com/&quot; target=&quot;_blank&quot;&gt;Delicious&lt;/a&gt; with a single click.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Colorzilla&lt;/strong&gt;
For web designers, developers or anyone working with graphics this is an eyedropper tool for picking colours. By clicking the tiny icon in the status bar you geta crosshair which when clicked on any pixel on screen gives the colour references in both Hexadecimal and RGB 0-255 values. This is incredibly useful if you see a colour you want to use. It also has the option to copy the various colour values straight to the clipboard.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Web Developer Toolbar&lt;/strong&gt;
Quite specifically for the web designer or web developer this toolbar has buttons which strip down the web page in the browser window to its various elements. You can view just CSS (styling), just images, identitfy different layers (div tags) - just about anyhting you might want to know about a page is there.&lt;/p&gt;
&lt;p&gt;If anyone reading knows of any other useful add-ons please feel free to share.&lt;/p&gt;
</description>
      <pubDate>Fri, 01 May 2009 11:28:35 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2009/my-firefox-add-ons/</guid>
    </item>
    <item>
      <title>Online ways to launch a website</title>
      <link>https://chrissmith.xyz/blog/2009/online-ways-to-launch-a-website/</link>
      <description>&lt;p&gt;In the offline world when you create a new publication, like a brochure or catalog, you need to plan its distribution. You need to get it in front of your potential customers. Online is no different.&lt;/p&gt;
&lt;p&gt;Too many people out there still seem to think that having a website built is the job done. Get a website and then sit back and wait for people to visit it. Wrong. The offline equivalent is having your brochures printed and then leaving them in their boxes. Just building a website is not enough.&lt;/p&gt;
&lt;p&gt;So, what can you do to distribute it and get it in front of your online customers? Here are some simple steps that should help.&lt;/p&gt;
&lt;p&gt;Firstly, you need to change the way you view the website compared with a more traditional printed brochure. The website is not equalivalent to a brochure. Your website in isolation is not worth anything. No, really. It&#39;s completely worthless. Without any way to reach it it may as well not be there.&lt;/p&gt;
&lt;p&gt;The way to get it out there is by creating links to your site. These can be &lt;strong&gt;links&lt;/strong&gt; in emails, on other website&#39;s pages or on search engine results pages, like &lt;a href=&quot;https://www.google.co.uk/&quot; target=&quot;_blank&quot;&gt;Google&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To get your site to appear in the search engine results you need to let the search engines know that it exists. You can either submit it to the search engines manually or just create links to it from other sites and they will find it and do the rest.&lt;/p&gt;
&lt;p&gt;For more information on building links please see my other article &lt;a href=&quot;https://chrissmith.xyz/blog/links-link-exchanges-and-strategies&quot;&gt;Links, link exchanges and strategies&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It takes time to build links and get found through the search engine results pages so what else can you do? Well, this may be stating the obvious but tell people. Tell everyone. And I mean everyone. Even the people who you don&#39;t think will be interested may know someone who is.&lt;/p&gt;
&lt;p&gt;Ask for &lt;strong&gt;feedback&lt;/strong&gt;. Approach people and say you need their help and value their opinion. We all love to feel important, valued and that we can help someone else. Send them a link and ask for their feedback. Most of them will take a look and if they&#39;ve had a quick look it will increase their chances of remembering your site in the future.&lt;/p&gt;
&lt;p&gt;Win win win! One of the easiest ways to get people to visit a web page is to incentivise them, put something in it for them. Running a &lt;strong&gt;competition&lt;/strong&gt; is good. This will not only pull people in but may also have a viral effect as people forward links to your web page to friends and family. It also provides an opportunity to capture their data (only with their permission, of course) and approach them again in future.&lt;/p&gt;
&lt;p&gt;Use &lt;strong&gt;social networks&lt;/strong&gt;. By posting a link on &lt;a href=&quot;https://www.facebook.com/&quot; target=&quot;_blank&quot;&gt;facebook&lt;/a&gt; or &lt;a href=&quot;https://www.twitter.com/&quot; target=&quot;_blank&quot;&gt;twitter&lt;/a&gt; you can reach huge numbers of people in minutes and if they like what they see it can really snowball.&lt;/p&gt;
&lt;p&gt;In short, when you&#39;re budgeting for a new website you should add in some budget to launch it or it may not provide you with any value.&lt;/p&gt;
</description>
      <pubDate>Mon, 30 Mar 2009 14:27:49 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2009/online-ways-to-launch-a-website/</guid>
    </item>
    <item>
      <title>Web Development - it&#39;s not like building a shed</title>
      <link>https://chrissmith.xyz/blog/2009/web-development-its-not-like-building-a-shed/</link>
      <description>&lt;p&gt;I recently read a great blog post on sub-standard web developers and how to avoid them. If you&#39;re looking to get a website developed I&#39;d suggest you have a quick read of this: &lt;a href=&quot;https://www.marketingtom.com/2009/02/beware-web-developers-who-know-nada.html&quot; target=&quot;_blank&quot;&gt;Beware Web Developers Who Know Nada!&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As a web developer myself I find it incredibly frustrating that I&#39;m constantly losing web development work to graphic designers who know nothing about marketing on the web. Does your business really need a piece of online art or does it actually want to see some return? As I see it there are only two things that matter - 1) are people finding the site and 2) is it giving them what they came for?&lt;/p&gt;
&lt;p&gt;My other bugbear is that web development is as its name suggests &amp;quot;developmental&amp;quot;. It&#39;s not a one off bit of work - build it, take the money, next. To be really successful, a website needs to evolve to meet the needs of its users so requires an ongoing cycle of analysis, review and redevelopment. This doesn&#39;t have to mean lots of expense or contracts. It just means stopping every once in a while and thinking about what is working, what isn&#39;t working, how many enquiries are you getting, is the number going up or down?&lt;/p&gt;
&lt;p&gt;If you&#39;re serious about making money on the web, you need to be prepared to put a lot of work in yourself, not simply farm it out, and work closely with a web developer who understands what your business needs from your site.&lt;/p&gt;
</description>
      <pubDate>Mon, 23 Feb 2009 17:24:19 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2009/web-development-its-not-like-building-a-shed/</guid>
    </item>
    <item>
      <title>The new language of Social Media</title>
      <link>https://chrissmith.xyz/blog/2009/the-new-language-of-social-media/</link>
      <description>&lt;p&gt;As a linguist I find the evolution of language fascinating. The concept of Web 2.0 seems to have brought with it a whole new vocabulary, some new words and some new meanings for existing words. I’ve listed a few here. If you can think of any more I’ve missed please feel free to comment and add to it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Application&lt;/strong&gt;
An application is a program which runs on a social network. Applications can easily be shared and published.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Avatar&lt;/strong&gt;
A picture or graphic used online to represent a person’s identity. This could be a photo, a cartoon or often just an amusing graphic.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Blog&lt;/strong&gt;
Blog is short for weblog. A blog is like an online diary. It’s a series of articles or posts, with the date marked, generally updated quite regularly. These articles can be categorised, searched, tagged and consumed as RSS feeds.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Blogspace&lt;/strong&gt;
A network of blogs and all their interconnections.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Blogosphere&lt;/strong&gt;
See blogspace.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Comment&lt;/strong&gt;
It’s common now for articles or blogs to allow their readers to interact with the content by posting a comment. These are usually found directly below the article or post. Some sites require you to create an account to comment, others simply that you provide your email address. Similarly, some comments have to be approved before they will appear, others don&#39;t.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Consume&lt;/strong&gt;
This is often used with feeds. Feeds can be consumed. This means that the feed content is reused and reposted elsewhere on the web.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fan&lt;/strong&gt;
Becoming a fan of another user or a page means you receive notifications of their activity.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Feed&lt;/strong&gt;
A feed, also called a newsfeed or RSS feed, is a small portable file which shares a summary list of a website’s content. For example, a news site might make its headlines available for sharing. Feeds are often denoted by an orange button with white markings.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Feed Reader&lt;/strong&gt;
A feed reader is a piece of software which consumes a feed, interprets the data contained in the feed and makes it available to read in a user friendly form.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Friend&lt;/strong&gt;
A friend is somebody with whom you have a network connection on a social media site. Unlike the traditional sense of the word a friend in Web 2.0 can be someone you’ve never met and never intend to.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Like&lt;/strong&gt;
You can show that you like content on social media sites by clicking a like link. Some sites use a thumbs up icon to represent the same idea.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Mashup &lt;/strong&gt;(sometimes written &amp;quot;mash-up&amp;quot; or &amp;quot;mash up&amp;quot;)
A mashup is the combining of content from different sources to create a new entity.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Newsfeed&lt;/strong&gt;
See feed.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ping&lt;/strong&gt;
A notification from a website, usually about updated content.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pingback&lt;/strong&gt;
A pingback is a link back to a site that allows an author to see who is linking to his/her document.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Podcast &lt;/strong&gt;(sometimes written &amp;quot;pod cast&amp;quot;)
Content designed to be played back on personal media players, typically mp3 or video files.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Profile&lt;/strong&gt;
A page about a person or organisation featuring information, photos, video and applications.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Report&lt;/strong&gt;
Wherever users are allowed to publish content there is potential for it to be abused. Many sites now offer an option to report inappropriate or abusive content.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Re-tweet &lt;/strong&gt;(sometimes written &amp;quot;retweet&amp;quot;)
To re-tweet is to reply to a post on social media site &lt;a href=&quot;https://www.twitter.com/&quot; target=&quot;_blank&quot;&gt;Twitter&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;RSS Feed&lt;/strong&gt;
See feed.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Sidebar&lt;/strong&gt;
A sidebar is a vertical running menu in a blog or web page. These often control the site’s navigation as well as other widgets.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Sping&lt;/strong&gt;
A sping is a ping or notification from a fake blog or splog.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Splog&lt;/strong&gt;
A splog is a fake blog, derived from “spam” and “blog”. A splog will use content from another site and have no original content of its own. They exist to drive traffic to other sites or to make money from advertising.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Status&lt;/strong&gt;
The status is a one line post on what a user is doing. It’s an easy way of keeping other users up to date with what you are doing, thinking or feeling. Other users are free to comment on your status.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tag&lt;/strong&gt;
Tagging a document means labelling it or assigning keywords to it. By tagging an article it makes it categorises it by your chosen keyword or tag making it easier to find.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Trackback&lt;/strong&gt;
A trackback is a link that lets an author know who is linking to their article. It’s really just a reference which the author can see.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tweet&lt;/strong&gt;
Tweeting simply means posting content on the social networking site &lt;a href=&quot;https://www.twitter.com/&quot; target=&quot;_blank&quot;&gt;Twitter&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Unlike&lt;/strong&gt;
Where there are options to say that you like something, there is also the option to “unlike” something. This is different from saying you dislike it, it is merely revoking your “like”.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Unfollow&lt;/strong&gt;
Some sites such as Twitter allow you to follow another person’s work or blog. To stop following somebody you “Unfollow” them.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Unlist&lt;/strong&gt;
If you have listed something, e.g. your website in a directory, then you can “unlist” it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Vlog&lt;/strong&gt;
A vlog is a video blog, a blog where all the content is in video format.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Vodcast&lt;/strong&gt;
Vodcasting is podcasting using video.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Wall&lt;/strong&gt;
An area on a page or profile where people can post. The owner has editorial control.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Widget&lt;/strong&gt;
A widget is a small program which usually sits in a sidebar.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Wiki&lt;/strong&gt;
A wiki is a website where the content is created by its users. The biggest and most famous example is &lt;a href=&quot;https://www.wikipedia.org/&quot; target=&quot;_blank&quot;&gt;Wikipedia&lt;/a&gt;.&lt;/p&gt;
</description>
      <pubDate>Wed, 18 Feb 2009 13:59:35 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2009/the-new-language-of-social-media/</guid>
    </item>
    <item>
      <title>Marketing through Facebook, for free</title>
      <link>https://chrissmith.xyz/blog/2009/marketing-through-facebook-for-free/</link>
      <description>&lt;p&gt;Facebook is the fastest growing, most popular networking tool in the UK today. For many users it has made personal emails a thing of the past. How can this be turned into an opportunity for businesses?&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.facebook.com/&quot; target=&quot;_blank&quot;&gt;Facebook&lt;/a&gt; is about people, real individuals. If you want to promote a company&#39;s goods or services on &lt;a href=&quot;https://www.facebook.com/&quot; target=&quot;_blank&quot;&gt;Facebook&lt;/a&gt; you can&#39;t just set up a business account - you have to do so from an individual&#39;s perspective. So, what can you do?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Create a Profile&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;On your profile write about the company / products / services you want to promote. At first you may think that&#39;s it&#39;s only friends and family who will be reading it but open it up to Friends of Friends and that&#39;s a huge network of people potentially taking a look at your profile. This kind of personal endorsement of a company/product/service is very powerful and people will sit up and take much more notice of this than an ad.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Create Groups, Events and Pages&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.facebook.com/&quot; target=&quot;_blank&quot;&gt;Facebook&lt;/a&gt; allows you to create a group for anything you wish. This allows discussion and sharing of media around the group&#39;s theme. On joining a group all user&#39;s friends are notified via the main feed so the potential to grow very quickly is huge. Once a group has members there are options for the group admin to contact all members so it&#39;s a quick and easy mailing list which manages itself. Events are similar to groups but for a limited timespan. Event invitations are highly effective as they ask for a response. &lt;a href=&quot;https://www.facebook.com/pages/create.php&quot; target=&quot;_blank&quot;&gt;Pages&lt;/a&gt; are again similar to groups but allow more in the way of content. Both events and pages have more prominence within individuals&#39; profiles so greater exposure than groups.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Get into the News Feed&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This displays a summary of actions performed by a user&#39;s friends. The more you can feature your content in this feed, the more attention you will get and drive more traffic to your group, event or page.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Import your Existing Content&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you have a website using an RSS Feed then &lt;a href=&quot;https://www.facebook.com/&quot; target=&quot;_blank&quot;&gt;Facebook&lt;/a&gt; allows you to import this into your profile or page, writing content to the news feed with each update. Here&#39;s my own &lt;a href=&quot;https://www.facebook.com/home.php?src=fftb#/pages/Chris-Smith-Web-Development/6761319987&quot; target=&quot;_blank&quot;&gt;web development Facebook Page&lt;/a&gt; which imports the content from my web development RSS feed.&lt;a href=&quot;https://www.facebook.com/home.php?src=fftb#/pages/Chris-Smith-Web-Development/6761319987&quot; target=&quot;_blank&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;And finally, a couple of don&#39;ts...&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Don&#39;t try to stay anonymous and set up a fake account. &lt;a href=&quot;https://www.facebook.com/&quot; target=&quot;_blank&quot;&gt;Facebook&lt;/a&gt; is about individuals and transparency. If you set up a fake account it&#39;s only a matter of time before it&#39;s deleted.&lt;/p&gt;
&lt;p&gt;Don&#39;t try to contact lots of individuals using Messages. &lt;a href=&quot;https://www.facebook.com/&quot; target=&quot;_blank&quot;&gt;Facebook&lt;/a&gt; is very hot on spotting spam and if you send the same message to lots of individuals you will quickly get blocked from sending any.&lt;/p&gt;
</description>
      <pubDate>Mon, 26 Jan 2009 15:08:46 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2009/marketing-through-facebook-for-free/</guid>
    </item>
    <item>
      <title>My Software Preferences</title>
      <link>https://chrissmith.xyz/blog/2009/my-software-preferences/</link>
      <description>&lt;p&gt;I just bought a new laptop and have spent a couple of long evenings setting it up. After babysitting it through the initial tedium of installing, connecting, updating, registering - lots of watching progress bars and restarting the machine every few minutes, I realised that I have my own strong ideas about which software I&#39;m going to use for various tasks.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://free.avg.com/&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;alignright&quot; style=&quot;float: right;border: 0;margin-left: 10px;margin-right: 10px;margin-top: 20px;margin-bottom: 20px&quot; src=&quot;https://free.avg.com/stc/tpl/crp/img/frt/avg_logo_en.gif&quot; alt=&quot;AVG Free&quot; width=&quot;240&quot; height=&quot;67&quot; /&gt;&lt;/a&gt;&lt;strong&gt;Security&lt;/strong&gt;
Top of the priority list is security and getting some good anti-virus, anti-spyware software in place. I uninstalled the &lt;a href=&quot;https://www.mcafee.com/&quot; target=&quot;_blank&quot;&gt;McAfee&lt;/a&gt; 30 day trial. I&#39;m sure it&#39;s excellent but why pay a subscription fee when there are free alternatives. I downloaded and installed &lt;a href=&quot;https://free.avg.com/&quot; target=&quot;_blank&quot;&gt;AVG Free&lt;/a&gt; Version, which is free for home use. It performs scans and updates itself automatically keeping your PC safe.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.mozilla-europe.org/en/firefox/&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;alignright&quot; style=&quot;border: 0pt none;margin: 20px;float: right&quot; src=&quot;https://www.mozilla-europe.org/img/image-library/firefox-wordmark-horizontal_small.png&quot; alt=&quot;Mozilla Firefox&quot; width=&quot;206&quot; height=&quot;96&quot; /&gt;&lt;/a&gt;&lt;strong&gt;Web Browsing&lt;/strong&gt;
Windows Vista comes with &lt;a href=&quot;https://www.microsoft.com/windows/products/winfamily/ie/default.mspx&quot; target=&quot;_blank&quot;&gt;Microsoft Internet Explorer&lt;/a&gt; (IE) installed but personally I find that &lt;a href=&quot;https://www.mozilla-europe.org/en/firefox/&quot; target=&quot;_blank&quot;&gt;Mozilla Firefox&lt;/a&gt; offers a much better web browsing experience. It&#39;s noticeably faster and the add-ons available mean that you can really customise it for your own needs. My personal favourites are &lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/1865&quot; target=&quot;_blank&quot;&gt;Adblock Plus&lt;/a&gt;, which collapses known ads in web pages and, of course, &lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/60&quot; target=&quot;_blank&quot;&gt;Web Developer&lt;/a&gt;, which provides all sorts of options and extra information about the web page you are browsing.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.openoffice.org/&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;alignright&quot; style=&quot;border: 0;float: right;margin-left: 10px;margin-right: 10px;margin-top: 20px;margin-bottom: 20px&quot; src=&quot;https://why.openoffice.org/images/why_home.gif&quot; alt=&quot;OpenOffice.org&quot; width=&quot;150&quot; height=&quot;105&quot; /&gt;&lt;/a&gt;&lt;strong&gt;Office - Word Processing, Spreadsheets, Presentations
&lt;/strong&gt;I boldly decided to ignore the 30 day free trials of &lt;a href=&quot;https://office.microsoft.com/&quot; target=&quot;_blank&quot;&gt;Microsoft Office&lt;/a&gt; (&lt;a href=&quot;https://office.microsoft.com/word&quot; target=&quot;_blank&quot;&gt;Word&lt;/a&gt;, &lt;a href=&quot;https://office.microsoft.com/excel&quot; target=&quot;_blank&quot;&gt;Excel&lt;/a&gt;, &lt;a href=&quot;https://office.microsoft.com/powerpoint&quot; target=&quot;_blank&quot;&gt;PowerPoint&lt;/a&gt;) and instead downloaded and installed &lt;a href=&quot;https://www.openoffice.org/&quot; target=&quot;_blank&quot;&gt;OpenOffice&lt;/a&gt;. It&#39;s open source which means the code behind the software is freely available for software developers to tinker with and suggest improvements. &lt;a href=&quot;https://www.openoffice.org/&quot; target=&quot;_blank&quot;&gt;OpenOffice&lt;/a&gt; is a suite of applications made up of Writer (word processing), Calc (spreadsheets), Impress (presentations/slideshows), Draw (graphics) and Base (databases). It&#39;s fully compatible with &lt;a href=&quot;https://office.microsoft.com/&quot; target=&quot;_blank&quot;&gt;Microsoft Office&lt;/a&gt; so you will always be able to open and edit anything you receive.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Web Development&lt;/strong&gt;
From my software choices so far it may sound like I&#39;m anti-&lt;a href=&quot;https://www.microsoft.com/&quot; target=&quot;_blank&quot;&gt;Microsoft&lt;/a&gt; but I&#39;m really not. I&#39;m just a big fan of open source software and the open collaboration. For my web development work I do love &lt;a href=&quot;https://msdn.microsoft.com/en-gb/vstudio/default.aspx&quot; target=&quot;_blank&quot;&gt;Microsoft Visual Studio&lt;/a&gt;. There&#39;s a lighter version of it called &lt;a href=&quot;https://www.microsoft.com/express/vwd/&quot; target=&quot;_blank&quot;&gt;Visual Web Developer&lt;/a&gt; which is free to download and use. This makes it easy, well, easier, to create dynamic database driven web applications.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.opensource.org/&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;alignleft&quot; style=&quot;float: left;border: 0;margin: 20px&quot; src=&quot;https://www.opensource.org/files/garland_logo.png&quot; alt=&quot;Open Source&quot; width=&quot;118&quot; height=&quot;100&quot; /&gt;&lt;/a&gt;In summary, there is a lot of free and open source software available and it&#39;s worth looking at your options rather than just going with the big names. Like me you might actually prefer some of the free software over the licensed and for the home user it could save you quite a bit of cash.&lt;/p&gt;
</description>
      <pubDate>Tue, 13 Jan 2009 14:43:24 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2009/my-software-preferences/</guid>
    </item>
    <item>
      <title>Moving from Print to Web in Stages</title>
      <link>https://chrissmith.xyz/blog/2009/moving-from-print-to-web-in-stages/</link>
      <description>&lt;p&gt;There are many good reasons for moving from producing printed publications such as leaflets, brochures or catalogues to putting all information onto a website - better for the environment, wider reaching, faster and cheaper. Even though we know this taking the plunge and stopping print media suddenly is scary.&lt;/p&gt;
&lt;p&gt;It doesn&#39;t have to be so sudden and drastic. It is possible to use a more gentle phased approach.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stage 1 - Getting the web right&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If this is going to work the website has to have the most up to date information, and if not exactly consitent with printed information, the web needs to be the most accurate source of information.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stage 2 - Produce a Digital Edition&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;When your publication is complete create what is called a digital edition or an electronic version of it which can be downloaded or emailed to people. The most common format for this is PDF but you can use anything which can be easily distributed electronically.&lt;/p&gt;
&lt;p&gt;Whilst a PDF download might not have quite the same feel as holding a high quality brochure in your hands there are advantages. Firstly, the customer gets it right away, whilst they&#39;re still interested. By the time a brochure arrives in the post the next day they may have gone off the idea or found a competitor&#39;s information online. The download also means that they can share it with friends or colleagues easily and at zero cost.&lt;/p&gt;
&lt;p&gt;Rather than launching both print and electronic media simultaneously it might be better to release the electronic version in advance. By doing this anyone waiting for the publication will have their information earlier and there&#39;s a good chance they may not feel the need for a print version.&lt;/p&gt;
&lt;p&gt;When it comes to the next edition of the publication it is worth considering the electronic means of distribution when it is designed. For example, if printed by the user, does it look good in black and white, does it fit onto A4?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stage 3 - Monitor publication requests&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Once you have both hard copy and electronic versions out there it&#39;s essential to monitor how many people are accessing the 2 types of media. You need to keep a note of how many hard copies are requested and compare this against numbers of downloads. Over time you should notice a natural increase in the downloads and this will, in turn, create a drop in the requests for print.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stage 4 - Use incentives&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;When trying to get numbers using the electronic media up and print down you can give people a nudge in the right direction by offering reduced prices online. Even those who don&#39;t use the internet might show an interest if they hear they can get something 10% cheaper.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stage 5 - Reduce print runs&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Rather than stop the publication altogether it may be preferable to reduce quantities slowly over time based on the demand you have been monitoring until you reach the point where the publication no longer offers a return on your investment.&lt;/p&gt;
</description>
      <pubDate>Fri, 09 Jan 2009 17:23:16 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2009/moving-from-print-to-web-in-stages/</guid>
    </item>
    <item>
      <title>Amazon - design a 4 year old can use</title>
      <link>https://chrissmith.xyz/blog/2009/amazon-design-a-4-year-old-can-use/</link>
      <description>&lt;p&gt;I was recently using &lt;a href=&quot;https://www.amazon.co.uk/&quot; target=&quot;_blank&quot;&gt;Amazon&lt;/a&gt; at home and my 4 year old son joined me. After I&#39;d completed my ordering he asked me if he could have a go. To put this in context he&#39;s at the stage where he can recognise brands (e.g. Tesco, M&amp;amp;S, etc.), his own name and a few letters but can&#39;t actually read other words.&lt;/p&gt;
&lt;p&gt;I found it fascinating to observe how he managed to use the site easily despite not being able to read.&lt;/p&gt;
&lt;p&gt;He clicked the logo taking him back to the home page. On there he saw a product image he liked (Star Wars video game), clicked it. On this page he clicked a play icon to watch a video preview of the game. When that ended he clicked the yellow button with a shopping basket icon to buy it. He then looked further down the screen where Amazon displays other related products - items other customers bought or viewed - and found some Star Wars toys. By following this process of clicking on related products and adding them to the basket he soon had over £300 of toys and video games in the basket. He even seemed to understand the product star rating system.&lt;/p&gt;
&lt;p&gt;This speaks volumes about how good the design of this site is.&lt;/p&gt;
&lt;p&gt;It can be navigated without any need for reading text. &lt;a href=&quot;https://www.amazon.co.uk/&quot; target=&quot;_blank&quot;&gt;Amazon&lt;/a&gt;&#39;s use of images and dynamically generating related images is superb. The human brain processes and recognises images and icons much faster than it can read text.&lt;/p&gt;
&lt;p&gt;It&#39;s obvious how to buy something even to someone with almost no previous internet experience. A clear button which stands out from the rest of the page bearing a shopping basket icon leaves no doubt about how you proceed to buy the product.&lt;/p&gt;
&lt;p&gt;One final tip - if you&#39;ve got young children make sure you don&#39;t leave yourself logged in to &lt;a href=&quot;https://www.amazon.co.uk/&quot; target=&quot;_blank&quot;&gt;Amazon&lt;/a&gt; or Father Christmas might be back sooner than you&#39;d expect.&lt;/p&gt;
</description>
      <pubDate>Thu, 08 Jan 2009 11:17:17 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2009/amazon-design-a-4-year-old-can-use/</guid>
    </item>
    <item>
      <title>Google&#39;s Personalised Search</title>
      <link>https://chrissmith.xyz/blog/2009/googles-personalised-search/</link>
      <description>&lt;p&gt;Search on the internet is changing. We all know how &lt;a href=&quot;https://www.google.co.uk/&quot; target=&quot;_blank&quot;&gt;Google&lt;/a&gt; works - you type in your search term, hit the &amp;quot;search button&amp;quot;, &lt;a href=&quot;https://www.google.co.uk/&quot; target=&quot;_blank&quot;&gt;Google&lt;/a&gt; beavers away in the background trying to match what you typed with the most likely matches and you&#39;re presented with a list of results, all within a split second.&lt;/p&gt;
&lt;p&gt;If you are logged into &lt;a href=&quot;https://www.google.co.uk/&quot; target=&quot;_blank&quot;&gt;Google&lt;/a&gt; when you do the same search things are now slightly different. Once the results come back you are given further options. You can &amp;quot;promote&amp;quot; a site by clicking on the little up arrow next to it. This is your way of saying that this is the site you wanted and it will push it to the top of the list for next time you do that search. You also have the option of clicking &amp;quot;remove&amp;quot;, the cross. This means that the result is not relevant to you and won&#39;t be shown next time around. Finally, you can &amp;quot;comment&amp;quot; by clicking on the speech bubble. This allows you to make notes as you go.&lt;/p&gt;
&lt;p&gt;It doesn&#39;t stop there though. &lt;a href=&quot;https://www.google.co.uk/&quot; target=&quot;_blank&quot;&gt;Google&lt;/a&gt; doesn&#39;t just remember your feedback on searches you have done but uses this information to predict your areas of interest. For example, if I do a search for &amp;quot;ajax&amp;quot; it will, in all probability, return results on Ajax the web programming technology. For someone else with no interest in web development but an interest in football it may return results on the Dutch football team.&lt;/p&gt;
&lt;p&gt;The wider effect of this new personalised search is that as people start making use of it then what one person sees when they perform a search may not be what another person sees. In fact, after prolonged use it almost definitely won&#39;t be. This means that the &lt;a href=&quot;https://www.seoexpert.org.uk/&quot; target=&quot;_blank&quot;&gt;SEO&lt;/a&gt; companies who claim that they will get you top rankings on &lt;a href=&quot;https://www.google.co.uk/&quot; target=&quot;_blank&quot;&gt;Google&lt;/a&gt; will no longer be able to measure how well your site is faring. They will be forced to revert to using numbers of visitors to a website as a measure of success instead, which, as any marketing person will tell you, is the only real measure anyway.&lt;/p&gt;
</description>
      <pubDate>Tue, 06 Jan 2009 11:42:21 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2009/googles-personalised-search/</guid>
    </item>
    <item>
      <title>I want an ecommerce site. Maybe you don&#39;t?</title>
      <link>https://chrissmith.xyz/blog/2008/i-want-an-ecommerce-site-maybe-you-dont/</link>
      <description>&lt;p&gt;I often get invited to quote for designing ecommerce sites or online stores and more often than not I actually decline the invitation. I don&#39;t feel it&#39;s morally right to invest my time and a customer&#39;s money in something that is doomed to failure.&lt;/p&gt;
&lt;p&gt;It&#39;s not that people have bad ideas, it&#39;s just that they don&#39;t have a business plan. I think most of us know that most new businesses fail in their first year and online businesses are no different. All too often people see having a website as the answer when it&#39;s only part of a larger process. I get the feeling that people still believe that they can spend money on a new website and then sit back and wait for the orders to come in.&lt;/p&gt;
&lt;p&gt;Whilst having your own ecommerce site or online business is appealing it is a big initial investment for a new business and you should consider how many sales you&#39;d need to cover the cost. If you can&#39;t be sure that you can recover this cost within a reasonable timescale you shouldn&#39;t take the risk.&lt;/p&gt;
&lt;p&gt;There are other ways. I often advise people starting out on a new venture to start off selling through &lt;a href=&quot;https://www.ebay.co.uk/&quot; target=&quot;_blank&quot;&gt;eBay&lt;/a&gt;. You pay a nominal amount to list your products and have to give eBay a percentage of your revenue but this is a lot cheaper and less risky than shelling out for a website. After a time, if you feel that there is a proven market and that you can make a profit then you can look at running your own site. Hopefully, if things have gone well, you&#39;ll have a bit of money in the bank to invest too.&lt;/p&gt;
</description>
      <pubDate>Mon, 08 Dec 2008 14:07:34 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2008/i-want-an-ecommerce-site-maybe-you-dont/</guid>
    </item>
    <item>
      <title>eMarketing Award Distinction :)</title>
      <link>https://chrissmith.xyz/blog/2008/emarketing-award-distinction/</link>
      <description>&lt;p&gt;This summer I studied the &lt;a title=&quot;CIM&quot; rel=&quot;nofollow&quot; href=&quot;https://www.cim.co.uk/&quot; target=&quot;_blank&quot;&gt;Chartered Institute of Marketing&lt;/a&gt; (CIM)&#39;s &lt;a title=&quot;eMarketing Award&quot; rel=&quot;nofollow&quot; href=&quot;https://www.marketingtom.com/emarketing_award.html&quot; target=&quot;_blank&quot;&gt;eMarketing Award&lt;/a&gt;. Last night I got my results in the post...&lt;/p&gt;
&lt;p&gt;I&#39;m proud to say that I achieved &lt;strong&gt;grade A distinctions&lt;/strong&gt; in both my online examination and 4,000 word eMarketing report.&lt;/p&gt;
&lt;p&gt;The course covers all aspects of &lt;strong&gt;electronic marketing&lt;/strong&gt;.  I studied with &lt;a title=&quot;Marketing Tom&quot; rel=&quot;nofollow&quot; href=&quot;https://www.marketingtom.com/&quot; target=&quot;_blank&quot;&gt;Marketing Tom Media&lt;/a&gt;, a CIM approved centre based near Cardiff, and would certainly recommend both course and &lt;a href=&quot;https://www.marketingtom.com/&quot; target=&quot;_blank&quot;&gt;training provider&lt;/a&gt; to anyone interested in growing their business online.&lt;/p&gt;
&lt;p&gt;Perhaps what is most satisfying is that the report which I wrote is not simply being filed away as an academic exercise but is actually being used as a &lt;strong&gt;strategy&lt;/strong&gt; for a major organisation&#39;s &lt;strong&gt;electronic marketing activities&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;In addition to this I have taken on board many of the &lt;strong&gt;tactics&lt;/strong&gt; and &lt;strong&gt;resources&lt;/strong&gt; covered by the course and have &lt;strong&gt;successfully grown&lt;/strong&gt; a number of websites. Since attending the course I have rebuilt this website and started using lots of online resources, my favourite being FeedBurner. My site now gets 3 to 4 times the &lt;strong&gt;traffic &lt;/strong&gt;it had previously, ranks much higher in &lt;strong&gt;Google&lt;/strong&gt; search listings and has brought in &lt;strong&gt;more enquiries&lt;/strong&gt;, which is the real measure of its success.&lt;/p&gt;
</description>
      <pubDate>Fri, 05 Dec 2008 14:37:23 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2008/emarketing-award-distinction/</guid>
    </item>
    <item>
      <title>The Cheap Web Design Market</title>
      <link>https://chrissmith.xyz/blog/2008/the-cheap-web-design-market/</link>
      <description>&lt;p&gt;A look at what awaits &amp;quot;cheap web design&amp;quot; seekers.&lt;/p&gt;
&lt;p&gt;I&#39;ve been running my own web development business since 2004 and in that time I have noticed a few changes to this market. There&#39;s far more competition now than there was a few years ago. If you do a Google search for &amp;quot;cheap web design&amp;quot;, &amp;quot;budget web design&amp;quot; or &amp;quot;affordable web design&amp;quot; then there are a lot of web pages out there with those page titles.&lt;/p&gt;
&lt;p&gt;What I find curious is that the web design product or service being offered in this market and the pricing structures don&#39;t seem to have moved on since 2004.&lt;/p&gt;
&lt;p&gt;The vast majority of companies competing in this market still seem to be offering very basic static brochure sites. The process here is 1) the client sends text and images to the web designer, 2) the designer puts them in HTML pages, 3) repeat stages 1 and 2. This means that if the client needs to make a change to the website&#39;s information - new products, price changes, news updates, etc. - he or she needs to go through the designer who probably charges a modest (if you&#39;re lucky) fee for the work.&lt;/p&gt;
&lt;p&gt;Much stranger than the product on offer though is the pricing structure. The majority of these seem to be sold as packages (design, hosting, email) based on the number of pages in the site. This makes no sense to me at all. It&#39;s usual for all pages within a website to have a similar look and feel. They generally all use a common template which includes the header, footer and navigation menus along with any styles (fonts, colours, etc.) used throughout the site. Therefore, most of the web designer&#39;s work goes into creating this template. Once this is designed it makes little difference whether a website has 1 page or 100. It&#39;s very curious then that so many of these companies offering &amp;quot;cheap web design&amp;quot; will offer, for example, a 4 page site for £150 but a 6 page site will set you back £350. That&#39;s a £200 jump in price for what I&#39;d estimate to be half an hour&#39;s work. Cheap web design doesn&#39;t have to mean a small website and a large website doesn&#39;t have to cost the earth.&lt;/p&gt;
&lt;p&gt;Chris Smith Web Development offers something different. I offer not static web pages but an installation of a content management system. This means that rather than having to come back to me to make changes to your pages you can simply log in and do it yourself, whenever and wherever you want to. No delays and no additional fees. The pricing is based on the template design so there&#39;s no limit on how many pages you can have. All you have to do is log in, select the Write Page option, write your content, click on Publish and it&#39;s there for the world to see, as many times as you like. You can go back and edit or delete pages, reorder them, change their titles whenever you want to.&lt;/p&gt;
&lt;p&gt;Since 2004 I &lt;em&gt;have&lt;/em&gt; moved on and have developed a better product. Static sites, charged for by the page, are no match for the flexibility and freedom offered by a content management system.&lt;/p&gt;
</description>
      <pubDate>Tue, 28 Oct 2008 15:39:38 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2008/the-cheap-web-design-market/</guid>
    </item>
    <item>
      <title>The Information Hungry Search Box</title>
      <link>https://chrissmith.xyz/blog/2008/the-information-hungry-search-box/</link>
      <description>&lt;p&gt;We&#39;re all used to the idea of search boxes on websites. The visitor types in a word or series of words which are then used to filter database results or web pages and return a list of matching results. It&#39;s a quick and easy way of finding something without having to drill down through endless options.&lt;/p&gt;
&lt;p&gt;From the web developer&#39;s point of view it&#39;s a great tool which increases a website&#39;s usability. From the web marketer&#39;s point of view it can do more.&lt;/p&gt;
&lt;p&gt;By capturing the text typed into the search box the website owner can see what his/her visitors are searching for. This may be for existing products or it could be that they are searching for something not offered. Capturing and analysing this information can help have several benefits.&lt;/p&gt;
&lt;p&gt;It can show where perhaps the wrong keywords are being used. It&#39;s unwise to advertise the services of a &amp;quot;Heating Engineer&amp;quot; when everybody is searching for a &amp;quot;plumber&amp;quot;. Finding the right keywords allows you to change your text and tags and bring you closer to your potential customers.&lt;/p&gt;
&lt;p&gt;It can help to shape a website&#39;s navigation. If a particular area is of far greater interest than others it can be made more prominent on the site. You may even notice seasonal trends.&lt;/p&gt;
&lt;p&gt;Where the search text is for products or services not offered by the website it brings the opportunity of developing the product/service range or working with partners to deliver these to the website visitor.&lt;/p&gt;
&lt;p&gt;To effectively capture this kind of data you need to not only log the text eneterd into the search box but also the time, date and the user&#39;s IP address. This additional information allows you to spot any duplicate results - there&#39;s a big difference between one person searching for something ten times and ten people searching for something once. The date and time data allows you to see any seasonal trends or possible responses to any other marketing campaigns.&lt;/p&gt;
&lt;p&gt;Even on a small website, which wouldn&#39;t normally merit a search box, using this tool can provide you quickly and easily with details of what your website visitors want.&lt;/p&gt;
</description>
      <pubDate>Mon, 27 Oct 2008 13:04:32 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2008/the-information-hungry-search-box/</guid>
    </item>
    <item>
      <title>Website Design - the Finishing Touches</title>
      <link>https://chrissmith.xyz/blog/2008/website-design-the-finishing-touches/</link>
      <description>&lt;p&gt;What separates a good website design from a great website design? On the surface they may both look the same but with great design come all the finishing touches, all those little details which make your site look that little bit more professional and, more importantly, perform better.&lt;/p&gt;
&lt;p&gt;If you&#39;ve got a website already has your designer provided all of these?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Favicon
&lt;/strong&gt;Favicon is short for &amp;quot;Favorites&amp;quot; icon and is the little graphic which is displayed when your site is bookmarked. It appears in your list of &amp;quot;Favorites&amp;quot; or Bookmarks, on your desktop if someone places a shortcut to a website there and in the address bar and on the tab in your web browser.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Email
&lt;/strong&gt;When a web developer is setting up your website it&#39;s reasonable to expect that they set up your email using the same domain at the same time. This can be done in several ways - forward all mail to an existing account, set up a new mailbox or set up a catch all account whereby anything sent to your domain will be delivered to you.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Email Filters
&lt;/strong&gt;As well as email you should also expect anti-virus and anti-spam filters to be applied.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Email Autoresponders
&lt;/strong&gt;Your email can be configured to automatically respond to incoming mail. This is useful to reassure your website visitors that the email they sent or form they submitted has been received. It can also provide useful information like alternative contact details, when they can expect a response or point them towards an area of your website, e.g. FAQ, or make them aware of your latest promotion.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Sitemap
&lt;/strong&gt;If your site is larger than 7 pages it&#39;s good practice to include a sitemap, an easy place for your visitors to go and see the contents of your website at a glance. This is also very good for search engine ranking as it reinforces your site structure and offers more internal links to be crawled.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;XML Sitemap
&lt;/strong&gt;A &lt;a href=&quot;https://www.google.com/webmasters/tools/docs/en/protocol.html&quot; target=&quot;_blank&quot;&gt;Google XML Sitemap&lt;/a&gt; is a small XML data file which lists the pages in your site. It&#39;s in a specific format which Google recognises and it gives you greater recognition by the major search engines. The same format is now also used by Yahoo! and Live. By not creating this and submitting it to Google you risk a great delay in your site being indexed and people finding it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Robots.txt
&lt;/strong&gt;This is a small text file which tells search engine robots which parts of your site they can access and index. It is also used to signpost the XML sitemap file. Without this your sitemap might not be found.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Search Engine and Directory Submission
&lt;/strong&gt;Once your website is finished the next step is getting it found. Some web designers feel that this is where their job ends and someone&#39;s else&#39;s begins. Others will take this on and actively try to make the website work for their client. A good practice when launching a new site is to submit it to the search engines so that they crawl and index it. It&#39;s also advisable to submit your site to as many directory sites as possible. There are thousands out there which accept listings free of charge and this helps to build up incoming links to your site which may or may not help with search engine ranking but will certainly give human web users the opportunity to follow links in to your site.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Marketing Advice
&lt;/strong&gt;Rather than just leaving you to it a great web designer will pass on useful information and advice on how to grow your site and make it as successful as possible. It is amazing how many do the design job and walk away when it is in their interest to create sites which work for their clients.&lt;/p&gt;
&lt;p&gt;When buying web development services it&#39;s important to check exactly what you&#39;re getting for your money. When you have a website designed by Chris Smith all of these finishing touches come as standard.&lt;/p&gt;
</description>
      <pubDate>Wed, 15 Oct 2008 13:37:40 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2008/website-design-the-finishing-touches/</guid>
    </item>
    <item>
      <title>Basic Website Integration</title>
      <link>https://chrissmith.xyz/blog/2008/basic-website-integration/</link>
      <description>&lt;p&gt;Integration is, in simple terms, making your website fit in with the rest of your business. At a basic level it&#39;s about making everything consistent and not leaving any holes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Consistent Information&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Make sure that whatever information you have on your website is consistent with any offline information. Anything like details of a product or service should really be a word for word match as any anomalies could create confusion. Customers who are not sure what they&#39;re getting won&#39;t buy. Don&#39;t kid yourself that they&#39;ll phone and check; they&#39;ll find the next website.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Customer Contact&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Unlike a physical business your website is accessible 24 hours a day. Therefore, if you provide a phone number on your site you should make it clear when people can use it. If it just rings and rings they may not call back. You should either put clear calling hours against it, offer an answering service or offer a callback facility. This last option has advantages for both you and your potential customer - the customer doesn&#39;t pay for the call and you don&#39;t miss out on capturing the customer&#39;s interest. Who knows if they&#39;d still feel like calling you at 9.00am the next morning?&lt;/p&gt;
&lt;p&gt;As well as phone contact you need to deal with form submisisons or emails in an appropriate way. Autoresponders are good. When the visitor sends you an email or submits a form they get an email just confirming that it has been received and will be dealth with. Set a realistic timescale for this, or better, set a timescale and then respond much quicker - exceed the customer&#39;s expectations.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Integrated Web Design&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A good web developer will not design your website as a stand alone unit but will look at how it integrates with your business needs.&lt;/p&gt;
</description>
      <pubDate>Tue, 14 Oct 2008 13:16:38 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2008/basic-website-integration/</guid>
    </item>
    <item>
      <title>Web Design for the non-designer</title>
      <link>https://chrissmith.xyz/blog/2008/web-design-for-the-non-designer/</link>
      <description>&lt;p&gt;The first thing to do is to have a clear distinction in your head between content and style. Content is the text and images that visitors read and look at; style is how these are arranged, laid out and presented.The style side is where the web designer comes in. This is his/her main area of expertise and he/she will have the design skills to present your content in a way which communicates your message clearly and professionally.&lt;/p&gt;
&lt;p&gt;The content is the site owner&#39;s responsibility. In website marketing content is king. The main reason a visitor will come back to your site is because he/she found what they were looking for. The look and feel are very much secondary to this.&lt;/p&gt;
&lt;p&gt;Creating your content can appear a little daunting if you&#39;ve never thought about it before, even for a small site, but it&#39;s really quite simple if you approach it in the right way. You may not have designed a site before but you have used plenty of sites. The trick, as with any marketing, is to put yourself in the visitor&#39;s shoes. You need to consider:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;When they come to your site, what are their objectives - what might they want to go away with?&lt;/li&gt;
	&lt;li&gt;What information will they expect to see?&lt;/li&gt;
	&lt;li&gt;What other information might be helpful to them?&lt;/li&gt;
&lt;/ul&gt;
If you can consider these things you will satisfy your website&#39;s visitors. The next step is to check out the online competition.
&lt;ul&gt;
	&lt;li&gt;What do similar sites (your competitors) offer?&lt;/li&gt;
	&lt;li&gt;Can you offer anything that they don&#39;t?&lt;/li&gt;
	&lt;li&gt;Can you make your site more useable than theirs?&lt;/li&gt;
&lt;/ul&gt;
If you can give your website visitors what they want better than your competitors do you have a recipe for a successful site. Pair that with professional styling and your site will be a great success.
</description>
      <pubDate>Tue, 14 Oct 2008 12:53:48 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2008/web-design-for-the-non-designer/</guid>
    </item>
    <item>
      <title>Beat the Credit Crunch - Move Online</title>
      <link>https://chrissmith.xyz/blog/2008/beat-the-credit-crunch-move-online/</link>
      <description>&lt;p&gt;With all this financial doom and gloom in the media it&#39;s perfectly understandable that many businesses are looking to cut back on spending and play it safe until the economy is more stable.&lt;/p&gt;
&lt;p&gt;Starting a new website or investing money in website marketing is probably something that is generally viewed as an expense to be avoided in the current climate but a move towards web based business could actually save you money.&lt;/p&gt;
&lt;p&gt;We all know that paper publications like corporate brochures are in decline and electronic media are on the increase. Now could be the right time to make the leap.&lt;/p&gt;
&lt;p&gt;If you produce a brochure it&#39;s probably costing you thousands. You&#39;ve then got all the distribution costs - covering letters, envelopes, postage. With a website you&#39;ve got an initial cost (almost certainly lower than brochure print costs), some annual maintenance costs (hosting, backups) and then internet marketing costs (promoting your website to get your business found). The big cost difference online is that when you come to the next cycle you don&#39;t have this initial outlay again as you would with a brochure. There&#39;s a huge saving to be made.&lt;/p&gt;
&lt;p&gt;Moving your marketing publications from offline to online won&#39;t just save you thousands, it has other benefits. With a traditional brochure the only way of measuring its effectiveness is seeing which of its recipients go on to enquire and then which buy. In reality most companies don&#39;t even track this and don&#39;t really know whether or not their brochure works but carry on with it blindly more out of habit than anything. With a website and online marketing tools everything is tracked, logged and measurable. Consider the advantages of knowing all this:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;You will know how many people visit your website. With a brochure how many are read and how many go straight in the bin? You&#39;ve no idea.&lt;/li&gt;
	&lt;li&gt;You will know which products people are looking at. Again, with a brochure you&#39;re in the dark.&lt;/li&gt;
	&lt;li&gt;You will know how people found your site - from search engines, from other sites or by typing in your web address (from offline promotion).&lt;/li&gt;
	&lt;li&gt;With online advertising you will know exactly how many people have viewed your ad and how many have clicked it. Compare this with an ad in a newspaper or magazine - there&#39;s no easy way of knowing how effective it is.&lt;/li&gt;
&lt;/ul&gt;
Moving your marketing from offline to online will not only save you money but will provide you with exact data which can be used to inform your marketing decisions. This means better marketing and less money wasted on ineffective marketing.
</description>
      <pubDate>Tue, 14 Oct 2008 11:27:52 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2008/beat-the-credit-crunch-move-online/</guid>
    </item>
    <item>
      <title>Content Management Systems explained</title>
      <link>https://chrissmith.xyz/blog/2008/content-management-systems-explained/</link>
      <description>&lt;p&gt;You&#39;ve probably heard the phrase &lt;abbr title=&quot;Content Management System&quot;&gt;CMS&lt;/abbr&gt; or Content Management System. I&#39;ll explain what it is and some of the benefits.&lt;/p&gt;
&lt;p&gt;A &lt;abbr title=&quot;Content Management System&quot;&gt;CMS&lt;/abbr&gt; is a system which sits behind a website and allows you to edit a website easily. It&#39;s called a content management system because it specifically allows changes to the content of the website - the text, images and links on pages - but not the layout or design, which stays fixed.&lt;/p&gt;
&lt;p&gt;The usual method of changing web content is by logging in and gaining access to an admin or control panel. This gives options of creating, editing or deleting pages as well as setting up page order and hierarchy (which pages are sub-options of others).&lt;/p&gt;
&lt;p&gt;When it comes to editing pages this is normally done through a visual or &lt;abbr title=&quot;What You See Is What You Get&quot;&gt;WYSIWYG&lt;/abbr&gt; editor, which is short for &amp;quot;What You See Is What You Get&amp;quot; so no knowledge of HTML or web page coding is required. It&#39;s very easy to use, as easy as using Microsoft Word, probably easier. You write your page&#39;s content in a large text area and have buttons to help with formatting - Bold, Italics, Underline, bullets, numbering, text alignment, indent, etc. You may be able to select from a limited range of fonts though this is usually controlled by the design template to ensure a consistent look and feel throughout the site. The best part is, you don&#39;t even have to use the &lt;abbr title=&quot;What You See Is What You Get&quot;&gt;WYSIWYG&lt;/abbr&gt; editor - you can simply paste your content from another application, like Word.&lt;/p&gt;
&lt;p&gt;As well as working with text you can insert various media - images, video clips, audio files, Flash.&lt;/p&gt;
&lt;p&gt;So, what are the benefits? Well, the main benefit is that anyone can use it which means that your site can be managed by anyone. In a medium or large company that means anyone in a team, not just the IT person or contracted web design company. For a small private site it gives you full freedom to control your content and changes happen instantly - no more waiting for the web designer to make your changes.&lt;/p&gt;
&lt;p&gt;If you&#39;re still using a static website and relying on someone else to update it, it&#39;s time to take control and manage your own content.&lt;/p&gt;
</description>
      <pubDate>Tue, 07 Oct 2008 14:02:52 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2008/content-management-systems-explained/</guid>
    </item>
    <item>
      <title>Web Design for Different Screen Sizes</title>
      <link>https://chrissmith.xyz/blog/2008/web-design-for-different-screen-sizes/</link>
      <description>&lt;p&gt;When you design for print media you work with graphics and text and arrange them in a way that is both pleasing to the eye and conveys your message. With the web you have to do the same but there&#39;s a whole lot more to it.&lt;/p&gt;
&lt;p&gt;With print, the publication has a fixed size. With web design, the size of the page can vary. Imagine trying to paint a picture when your canvas keeps changing size. Users view web pages through different devices and different software with different screen resolutions. Most web pages are still viewed on a computer screen but these days can equally be viewed on mobile phones, PDAs, web books, even games consoles. In terms of software, the main web browsers are &lt;a href=&quot;https://www.microsoft.com/windows/products/winfamily/ie/default.mspx&quot; target=&quot;_blank&quot;&gt;Microsoft Internet Explorer&lt;/a&gt; and &lt;a href=&quot;https://www.mozilla.com/firefox/&quot; target=&quot;_blank&quot;&gt;Mozilla Firefox&lt;/a&gt; but there is a whole host of others. You may have heard of Chrome, &lt;a href=&quot;https://www.apple.com/safari/&quot; target=&quot;_blank&quot;&gt;Safari&lt;/a&gt;, &lt;a href=&quot;https://www.opera.com/&quot; target=&quot;_blank&quot;&gt;Opera&lt;/a&gt; and beyond that mobile devices use their own. Each web browser is a program designed to interpret and display web page code (HTML) but they all interpret it slightly differently so when writing the code you have to be sure it will display as you want it to. As well as conventional web browsers there are also specialised screen readers which read the text on a web page aloud for those with visual impairments. This is where accessible design comes into play. As if that wasn&#39;t enough to contend with, individual users also have different screen resolutions, some viewing the same content on a screen resolution 4 times larger than others.&lt;/p&gt;
&lt;p&gt;Areas of the screen can be stretched or squashed to fit with the screen size and, rather than being given fixed heights and widths, are given maximum and minimum dimensions within which they can move.&lt;/p&gt;
&lt;p&gt;So, when you look at a web page, you need to realise that what you see will probably not be exactly the same as what others see. The content should be the same but the layout will vary.&lt;/p&gt;
&lt;p&gt;As people buy newer computers with larger monitors and higher resolutions websites need to be redesigned. The majority of users in the UK use a Windows PC with Internet Explorer 7 and a screen resolution of 1024x768 pixels. Three years ago the typical UK user would have been using Internet Explorer version 6 with a screen resolution of only 800x600 pixels. If you haven&#39;t redesigned your website in the last 3 years it&#39;s time it was optimised for the new generation of visitors.&lt;/p&gt;
</description>
      <pubDate>Tue, 30 Sep 2008 15:01:48 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2008/web-design-for-different-screen-sizes/</guid>
    </item>
    <item>
      <title>Links, link exchanges and strategies</title>
      <link>https://chrissmith.xyz/blog/2008/links-link-exchanges-and-strategies/</link>
      <description>&lt;p&gt;There&#39;s so much written about links, linking strategies, link exchanges and so much conflicting advice out there. How do you know who or what to believe?&lt;/p&gt;
&lt;p&gt;Well, it&#39;s actually quite simple. Don&#39;t listen to anyone, not even me. When it comes to links and what you should do let&#39;s see what &lt;a href=&quot;https://www.google.co.uk/&quot; target=&quot;_blank&quot;&gt;Google&lt;/a&gt; has to say. &lt;a href=&quot;https://www.google.co.uk/&quot; target=&quot;_blank&quot;&gt;Google&lt;/a&gt; has a &lt;a href=&quot;https://www.google.com/webmasters/&quot; target=&quot;_blank&quot;&gt;Webmasters&lt;/a&gt; section of their site which gives clear guidelines of what you should and shouldn&#39;t do. Read it. Do it.&lt;/p&gt;
&lt;p&gt;On the subject of links this page is a good place to start: &lt;a href=&quot;https://www.google.com/support/webmasters/bin/answer.py?hl=en&amp;amp;answer=66356&quot; target=&quot;_blank&quot;&gt;Creating a Google-friendly site: Best practices &amp;gt; Link schemes&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Google&#39;s advice: &amp;quot;some webmasters engage in link exchange schemes and build partner pages exclusively for the sake of cross-linking, disregarding the quality of the links, the sources, and the long-term impact it will have on their sites. This is in violation of Google&#39;s webmaster guidelines and can negatively impact your site&#39;s ranking in search results.&amp;quot;&lt;/p&gt;
&lt;p&gt;In summary, links are important but it&#39;s about quality not just quantity.&lt;/p&gt;
&lt;p&gt;Getting links is difficult. If people like your site&#39;s content they will link to it. The more people link to it, the more people see it and so on in a snowball effect. But... how do you get people to like your content when nobody is viewing it because you don&#39;t have enough incoming links - it&#39;s a vicious circle. How do you get your little snowball started down the hill?&lt;/p&gt;
&lt;p&gt;Give it a little push. Here are 3 great ways to get going:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Add your site to directories, not any directory going but directories where the theme or content is relevant to your site. Try a Google search for your theme or industry plus the word &amp;quot;directory&amp;quot; or &amp;quot;listing&amp;quot; and see if you can add your site. You could also try &amp;quot;add site&amp;quot; or &amp;quot;submit your site&amp;quot; to see where you can get a free link. Before going too mad creating directory links remember it&#39;s about quality as well as quantity - it&#39;s all quite logical - a link from a site where you&#39;re allowed to add your own links isn&#39;t going to be worth as much as a link that someone else has chosen to add.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Get involved in forums or online communities. Find sites relevant to your site where you are allowed to contribute and join in. Don&#39;t be obvious and steam in advertising your site but get involved in discussions, try to help people out and, soon enough, if they&#39;re interested in what you&#39;ve got to say they&#39;ll look at your site.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Blog. Write articles or posts, just like this one, and post it on your own site or submit it to a blogging or article site. Be sure to include an interesting headline and some links back to your site. Submit this to the right blog search engines (e.g. &lt;a href=&quot;https://www.technorati.com/&quot; target=&quot;_blank&quot;&gt;Technorati&lt;/a&gt;, &lt;a href=&quot;https://www.digg.com/&quot; target=&quot;_blank&quot;&gt;Digg&lt;/a&gt;) and it will be read and passed around gaining you not only links but visitors in the process. Pssst - I know a very good blog designer.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
</description>
      <pubDate>Mon, 29 Sep 2008 13:45:46 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2008/links-link-exchanges-and-strategies/</guid>
    </item>
    <item>
      <title>What is a website visitor worth?</title>
      <link>https://chrissmith.xyz/blog/2008/what-is-a-website-visitor-worth/</link>
      <description>&lt;p&gt;When looking at investing money in trying to get more visitors to your website you need to first work out what a visitor is worth to you.&lt;/p&gt;
&lt;p&gt;So, how do you work it out? Well, to do it at a basic level is very simple. Choose a time period to analyse - the last 12 months, last 3 months, last 30 days, etc. Now, in this period see how much profit you made and how many visitors your website got. If you&#39;re using a web stats package, unique visitors is the figure to use here. Simply divide the number of unique visitors by the profit and this will give you a mean profit per visitor. You can use this as a basis for spending on gaining more visitors.&lt;/p&gt;
&lt;p&gt;Whilst more visitors means more profit you shouldn&#39;t just look at boosting traffic but try to actively increase the value of each online visitor. If a visitor becomes more likely to buy from you they become more valuable and investing money in attracting more visitors then gives you better value for money. So, as well as your traffic you also need to try to improve your conversion rate. The conversion rate is simply the proportion of visitors who buy. There are lots of things you can do to boost your conversion rates but that&#39;s for another day...&lt;/p&gt;
</description>
      <pubDate>Tue, 23 Sep 2008 11:29:26 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2008/what-is-a-website-visitor-worth/</guid>
    </item>
    <item>
      <title>Google Chrome - first impressions</title>
      <link>https://chrissmith.xyz/blog/2008/google-chrome-first-impressions/</link>
      <description>&lt;p&gt;I thought I&#39;d just give my tuppence worth on &lt;a href=&quot;https://www.google.co.uk/&quot; target=&quot;_blank&quot;&gt;Google&lt;/a&gt;&#39;s new BETA browser, &lt;a href=&quot;https://www.google.com/chrome&quot; target=&quot;_blank&quot;&gt;Chrome&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;When I first heard about &lt;a href=&quot;https://www.google.com/chrome&quot; target=&quot;_blank&quot;&gt;Google&#39;s new browser&lt;/a&gt; it was with dread. As a web developer an important part of developing any web page or application is testing that it works in the major browsers. Having another browser on the scene, and with a big name like &lt;a href=&quot;https://www.google.co.uk/&quot; target=&quot;_blank&quot;&gt;Google&lt;/a&gt; behind it you know it&#39;s going to have a lot of users, means more testing and increases my chances of having to recode.&lt;/p&gt;
&lt;p&gt;Before downloading it I read &lt;a href=&quot;https://www.google.co.uk/&quot; target=&quot;_blank&quot;&gt;Google&lt;/a&gt;&#39;s page on &lt;a href=&quot;https://www.google.com/chrome/intl/en-GB/why.html?hl=en-GB&quot; target=&quot;_blank&quot;&gt;Why We Built A Browser&lt;/a&gt;. The page itself is titled &amp;quot;A fresh take on the browser&amp;quot;. On it &lt;a href=&quot;https://www.google.co.uk/&quot; target=&quot;_blank&quot;&gt;Google&lt;/a&gt; openly admits &amp;quot;We&#39;ve used components from &lt;a href=&quot;https://www.apple.com/&quot; target=&quot;_blank&quot;&gt;Apple&lt;/a&gt;&#39;s &lt;a href=&quot;https://webkit.org/&quot; target=&quot;_blank&quot;&gt;WebKit&lt;/a&gt; and &lt;a href=&quot;https://www.mozilla.org/&quot; target=&quot;_blank&quot;&gt;Mozilla&lt;/a&gt;&#39;s &lt;a href=&quot;https://www.mozilla.com/firefox/&quot; target=&quot;_blank&quot;&gt;Firefox&lt;/a&gt;&amp;quot;. So, maybe not an entirely fresh take then?&lt;/p&gt;
&lt;p&gt;So, on going in, what are my first impressions? Well, first thought, it looks pretty much the same as &lt;a href=&quot;https://www.microsoft.com/windows/products/winfamily/ie/default.mspx&quot; target=&quot;_blank&quot;&gt;&lt;abbr title=&quot;Internet Explorer&quot;&gt;IE&lt;/abbr&gt;&lt;/a&gt; and &lt;a href=&quot;https://www.mozilla.com/firefox/&quot; target=&quot;_blank&quot;&gt;Firefox&lt;/a&gt;. The browsing tabs have been shifted above the address bar, which, as far as I can see, is just a change for change&#39;s sake rather than serving any useful purpose - why make people have to get used to something new when the browers they are used to work just fine? Other than that, without delving too deep, I&#39;m struggling to find anything radically different.&lt;/p&gt;
&lt;p&gt;On the plus side, it doesn&#39;t have loads of toolbars, keeping a nice clean, simple appearance - one of the great strengths of &lt;a href=&quot;https://www.google.co.uk/&quot; target=&quot;_blank&quot;&gt;Google&#39;s search engine&lt;/a&gt;. After using it for a while, I noticed that it remembers the sites you visit and uses this data intelligently to make it quicker to revisit them. It&#39;s fast too, noticeably quicker than &lt;a href=&quot;https://www.microsoft.com/windows/products&quot; target=&quot;_blank&quot;&gt;IE&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;On the negative side, it doesn&#39;t seem to handle RSS feeds and feed reading as well as &lt;a href=&quot;https://www.microsoft.com/windows/products&quot; target=&quot;_blank&quot;&gt;IE&lt;/a&gt; or &lt;a href=&quot;https://www.mozilla.com/firefox/&quot; target=&quot;_blank&quot;&gt;Firefox&lt;/a&gt; (with RSS add-ons) but I&#39;m sure this will come.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.mozilla.com/firefox/&quot; target=&quot;_blank&quot;&gt;Firefox&lt;/a&gt; has been the web professional&#39;s choice for years now and with good reason. So, will &lt;a href=&quot;https://www.google.com/chrome&quot; target=&quot;_blank&quot;&gt;Chrome&lt;/a&gt; offer us anything new that &lt;a href=&quot;https://www.mozilla.com/firefox/&quot; target=&quot;_blank&quot;&gt;Firefox&lt;/a&gt; can&#39;t? As I see it, the reason for &lt;a href=&quot;https://www.mozilla.com/firefox/&quot; target=&quot;_blank&quot;&gt;Firefox&lt;/a&gt;&#39;s success hasn&#39;t been about speed or security but freedom. It&#39;s great strength is that it&#39;s so easy to customise and ease of using &lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/&quot; target=&quot;_blank&quot;&gt;add-ons&lt;/a&gt; make it much more than a tool for reading web content. I&#39;m assuming that, being an open source project, &lt;a href=&quot;https://www.google.com/chrome&quot; target=&quot;_blank&quot;&gt;Chrome&lt;/a&gt; will follow suit.&lt;/p&gt;
&lt;p&gt;It seems a shame to me that all of the excellent developers out there who have been building add-ons for &lt;a href=&quot;https://www.mozilla.com/firefox/&quot; target=&quot;_blank&quot;&gt;Firefox&lt;/a&gt; will now be split between &lt;a href=&quot;https://www.mozilla.com/firefox/&quot; target=&quot;_blank&quot;&gt;Firefox&lt;/a&gt; and &lt;a href=&quot;https://www.google.com/chrome&quot; target=&quot;_blank&quot;&gt;Chrome&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I don&#39;t think that &lt;a href=&quot;https://www.google.co.uk/&quot; target=&quot;_blank&quot;&gt;Google&lt;/a&gt; will better &lt;a href=&quot;https://www.mozilla.com/firefox/&quot; target=&quot;_blank&quot;&gt;Firefox&lt;/a&gt; but they will be able to match it and with their finances and history of buying up big web companies (&lt;a href=&quot;https://www.youtube.com/&quot; target=&quot;_blank&quot;&gt;YouTube&lt;/a&gt;, &lt;a href=&quot;https://www.feedburner.com/&quot; target=&quot;_blank&quot;&gt;FeedBurner&lt;/a&gt;) I wouldn&#39;t be a bit surprised if we saw Google Firefox before too long.&lt;/p&gt;
&lt;p&gt;See what you think - &lt;a href=&quot;https://www.google.com/chrome&quot; target=&quot;_blank&quot;&gt;Google Chrome&lt;/a&gt;&lt;/p&gt;
</description>
      <pubDate>Mon, 15 Sep 2008 12:43:31 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2008/google-chrome-first-impressions/</guid>
    </item>
    <item>
      <title>The Web 2.0 concept - the basics</title>
      <link>https://chrissmith.xyz/blog/2008/the-web-20-concept-the-basics/</link>
      <description>&lt;p&gt;The days of having your website managed by a web designer or design company are now on their way out.&lt;/p&gt;
&lt;p&gt;In the past websites were a one-way read only process, an online brochure which people visited to get information. Now, with the whole concept of Web 2.0, it&#39;s all a two-way interactive process with customers or fans playing an active part in a website.&lt;/p&gt;
&lt;p&gt;Now, not only can you update all of your web pages or blogs yourself but you can also allow visitors to comment and discuss your website&#39;s content all over the internet, reaching far greater numbers of people than ever before.&lt;/p&gt;
&lt;p&gt;This two-way interaction not only improves communications with customers or fans but actually helps shape your products/services by allowing you to see where the demand is - who is buying and what they really want.&lt;/p&gt;
&lt;p&gt;With Web 2.0 your web presence goes way beyond what you put on your site. You now need to look at review sites, forums, online communities, social networking communities - in short, anywhere where people can make reference to you.&lt;/p&gt;
&lt;p&gt;When you&#39;re looking to launch a new web project make sure it fits into the world of Web 2.0 or risk being left behind.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Want to know more?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I recommend &lt;a href=&quot;https://www.oreillynet.com/pub/a/oreilly/tim/news/2005/09/30/what-is-web-20.html&quot; target=&quot;_blank&quot;&gt;O&#39;Reilly - What is Web 2.0?&lt;/a&gt;&lt;/p&gt;
</description>
      <pubDate>Mon, 11 Aug 2008 12:14:30 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2008/the-web-20-concept-the-basics/</guid>
    </item>
    <item>
      <title>The CIM eMarketing Award</title>
      <link>https://chrissmith.xyz/blog/2008/the-cim-emarketing-award/</link>
      <description>&lt;p&gt;I&#39;m currently studying towards the &lt;a title=&quot;CIM&quot; href=&quot;https://www.cim.co.uk/&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Chartered Institute of Marketing&lt;/a&gt; (CIM)&#39;s &lt;a title=&quot;eMarketing Award&quot; href=&quot;https://www.marketingtom.com/emarketing_award.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;eMarketing Award&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I did a 4 day intensive course through &lt;a title=&quot;Marketing Tom&quot; href=&quot;https://www.marketingtom.com/&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Marketing Tom Media&lt;/a&gt; based near Cardiff. The Award is assessed by an online test and a 4,000 word eMarketing report.&lt;/p&gt;
&lt;p&gt;EMarketing encompasses not only marketing through the web but all forms of electronic marketing so looks at things like email, interactive digital TV, mobile phones, CD-ROMs, etc. The web side looks at not only how to develop a successful website but all the other tools and tricks available to anyone looking to promote their business. It was a real eye opener for me. I now feel that I properly understand the meaning of Web 2.0 - blogging, RSS, social networking. Things have really moved on in the last few years and static brochure type websites are quickly being left behind by the new web 2.0 interactive sites which actively involve the customers in the whole web experience.&lt;/p&gt;
&lt;p&gt;The real beauty of online marketing compared to conventional forms of offline marketing is that everything is quantifiable. Every time anyone sees an advert it is logged. If they click a link it is logged. This makes it very easy to way up the return on your investment and keep your marketing budget going on the right things.&lt;/p&gt;
&lt;p&gt;As well as all the marketing hints and tips the course also looks at how eMarketing fits in with the rest of your business - customer service, data management, development of new products and services.&lt;/p&gt;
&lt;p&gt;All being well I hope to gain this professional qualification by the end of 2008.&lt;/p&gt;
</description>
      <pubDate>Thu, 07 Aug 2008 11:30:29 +0000</pubDate>
      <dc:creator>Chris Smith</dc:creator>
      <guid>https://chrissmith.xyz/blog/2008/the-cim-emarketing-award/</guid>
    </item>
  </channel>
</rss>