<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Nic</title>
    <description>The latest articles on DEV Community by Nic (@nicm42).</description>
    <link>https://dev.to/nicm42</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F527883%2F2ed41c10-319f-4438-b310-6bae6013b357.jpeg</url>
      <title>DEV Community: Nic</title>
      <link>https://dev.to/nicm42</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nicm42"/>
    <language>en</language>
    <item>
      <title>Trying AI autocomplete</title>
      <dc:creator>Nic</dc:creator>
      <pubDate>Sun, 12 Apr 2026 16:11:21 +0000</pubDate>
      <link>https://dev.to/nicm42/trying-ai-autocomplete-2bhc</link>
      <guid>https://dev.to/nicm42/trying-ai-autocomplete-2bhc</guid>
      <description>&lt;p&gt;I've used autocomplete before in coding - after all, why type more than you need to? But recently I downloaded Cursor and tried out the AI autocomplete, which can add many lines at a time. And did I find it useful? Well, yes and no.&lt;/p&gt;

&lt;p&gt;I've only tried it on a personal project. I do those because I have a fun idea and/or want to try a new language/framework and/or want to remind myself how to use an old one. The first thing it did was to guess correctly what I wanted to do with some data. Which was exciting, but also it wasn't something I do often in that language, so I sort of wanted to remember for myself how to do it. But if it was something I did a lot then I can see how it would be really good to save myself a lot of typing.&lt;/p&gt;

&lt;p&gt;The next thing it did was also helpful, except that it had an error on it. It was exactly the sort of error I'd also make, but I'd expected it to know better. Which I know is silly because it's just getting data from people who are also making the same mistake.&lt;/p&gt;

&lt;p&gt;After that its guesses about what I was trying to do were completely wrong and it was just annoying. But I've just been working on JavaScript at the moment. It'll be interesting to see how it does when I come to the CSS.&lt;/p&gt;

&lt;p&gt;In summary, I can see how it would be really useful at work, when it has all the context for what you're working on and the languages used. And it's all things you do every day and have a deadline on. But on personal projects the one line autocomplete is probably all I need - after all, I don't have a deadline on personal projects, I'm just enjoying working on them.&lt;/p&gt;

</description>
      <category>ai</category>
    </item>
    <item>
      <title>Moving elements with JavaScript</title>
      <dc:creator>Nic</dc:creator>
      <pubDate>Mon, 02 Mar 2026 17:40:25 +0000</pubDate>
      <link>https://dev.to/nicm42/moving-elements-with-javascript-f0j</link>
      <guid>https://dev.to/nicm42/moving-elements-with-javascript-f0j</guid>
      <description>&lt;p&gt;Recently I had a situation where there were two elements, A and B, each of which contained a whole load of things. On mobile A was at the top and B was below it. But on desktop B was on the left and A was on the right.&lt;/p&gt;

&lt;p&gt;Theoretically that's easy to fix - flexbox will sort that right out. However, that then meant that the focus order was wrong.&lt;/p&gt;

&lt;p&gt;But that's still an easy fix - you just duplicate one of the elements in the HTML and hide one on mobile and the other on desktop. Except that this is in a CMS and the HTML was being built by it and didn't exist as HTML to change. And there were a load of scripts doing things inside these elements, some of which could well depend on a unique ID or a class only being used once. It was an important page on the site, so if I broke it, things would go very wrong, so I didn't want to touch it.&lt;/p&gt;

&lt;p&gt;There will one day be some CSS to tackle this: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/reading-flow" rel="noopener noreferrer"&gt;reading-flow&lt;/a&gt;. But at the moment it's only available in Chromium browsers and is also marked as experimental, therefore subject to change and shouldn't be used in production code.&lt;/p&gt;

&lt;p&gt;Fortunately, there's a really simple JavaScript solution. What I did at desktop size was to move element B to be before element A. When you look at the resulting HTML it looks like it's always been that way round. And the focus goes through the element on the left, followed by the element on the right.&lt;/p&gt;

&lt;p&gt;The solution is &lt;code&gt;before&lt;/code&gt;. Or &lt;code&gt;after&lt;/code&gt;. Since I only have two elements they effectively do the same thing.&lt;/p&gt;

&lt;p&gt;To move element B before element A you use:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;a.before(b)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;or you can use&lt;/p&gt;

&lt;p&gt;&lt;code&gt;b.after(a)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Which is a bit confusing because if you read that from left to right it sounds like you're saying a is before b, or b is after a. But when you try it it's easy to tell you've done it wrong.&lt;/p&gt;

</description>
      <category>javascript</category>
    </item>
    <item>
      <title>Transitioning display: none</title>
      <dc:creator>Nic</dc:creator>
      <pubDate>Sat, 22 Nov 2025 14:25:17 +0000</pubDate>
      <link>https://dev.to/nicm42/transitioning-display-none-10kk</link>
      <guid>https://dev.to/nicm42/transitioning-display-none-10kk</guid>
      <description>&lt;p&gt;I recently had cause to transition display: none. It's not yet working in all browsers, but when I tried it I found the effect was so subtle that no one would notice the difference. In this example I had to change the transition time to 1 second in order to see it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The HTML
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Some text here&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;Toggle active state&lt;span class="nt"&gt;&amp;lt;/button&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Some JS to add the transition
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toggle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;is-active&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The CSS
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex-start&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;margin-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;4px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;4px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;red&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;opacity&lt;/span&gt; &lt;span class="m"&gt;1s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;display&lt;/span&gt; &lt;span class="m"&gt;1s&lt;/span&gt; &lt;span class="n"&gt;allow-discrete&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="nc"&gt;.is-active&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="err"&gt;@starting-style&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.5rem&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The transition
&lt;/h2&gt;

&lt;p&gt;A lot of that CSS is the set up, the transition bits we’re interested in are these bits:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;opacity&lt;/span&gt; &lt;span class="m"&gt;1s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;display&lt;/span&gt; &lt;span class="m"&gt;1s&lt;/span&gt; &lt;span class="n"&gt;allow-discrete&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="nc"&gt;.is-active&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="err"&gt;@starting-style&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Most of this is pretty standard. The span starts off with an opacity of 0 and display: none. The transition transitions opacity in 1s. And also display - which works because of the &lt;code&gt;allow-discrete&lt;/code&gt; keyword.&lt;/p&gt;

&lt;p&gt;And then when the is-active class is applied to the parent div we change it to be an opacity of 1 and display: block.&lt;/p&gt;

&lt;p&gt;The thing that actually makes this all work is this bit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@starting-style&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tells it that it's starting from an opacity of 0. You’d think it would know that because I told it it had an opacity of 0 when the is-active class is applied. But it needs to know within the is-active class too, so it knows how to transition the opacity in. If you remove this it will transition out, but not in. It's as if now the is-active class is applied it can no longer see the styles set on the div and you have to let it know what they are.&lt;/p&gt;

&lt;p&gt;Codepen decided not to run JS when I set this up, so here's a JSFiddle instead.&lt;/p&gt;

&lt;p&gt;

&lt;iframe src="https://jsfiddle.net/sytk9L73/1//embedded/result,html,css,js//dark" width="100%" height="600"&gt;
&lt;/iframe&gt;


&lt;/p&gt;

</description>
      <category>css</category>
    </item>
    <item>
      <title>Styling sibling hover and none hover</title>
      <dc:creator>Nic</dc:creator>
      <pubDate>Sun, 14 Sep 2025 11:26:47 +0000</pubDate>
      <link>https://dev.to/nicm42/styling-sibling-hover-and-none-hover-5bdl</link>
      <guid>https://dev.to/nicm42/styling-sibling-hover-and-none-hover-5bdl</guid>
      <description>&lt;p&gt;I recently had some complicated CSS to get my head around. I have a list of links which I want to style when they’re being hovered/focus on. But, if none of them are being hovered or focused, then I want to style the first one in the list.&lt;/p&gt;

&lt;h2&gt;
  
  
  The HTML
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;One&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Two&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Three&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Four&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Five&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Six&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Styling the hover/focus
&lt;/h2&gt;

&lt;p&gt;This is the simplest part - I am making the background of the links pink when they are hovered or focused.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="nd"&gt;:focus&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;pink&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Styling the first element
&lt;/h2&gt;

&lt;p&gt;Also, simple.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="nd"&gt;:first-of-type&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;pink&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Styling the siblings
&lt;/h2&gt;

&lt;p&gt;If we just make the hover/focus pink and the first element pink when we aren’t hovering/focusing then the first element is pink which is what we want. But then it keeps being pink even when we’re hovering/focusing on something else. What we need to do is to unstyle the siblings when one is being hovered/focused.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="nd"&gt;:has&lt;/span&gt;&lt;span class="o"&gt;(~&lt;/span&gt; &lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="nd"&gt;:has&lt;/span&gt;&lt;span class="o"&gt;(~&lt;/span&gt; &lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="nd"&gt;:focus&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;unset&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is saying that if an &lt;code&gt;li&lt;/code&gt; has a sibling with an &lt;code&gt;a&lt;/code&gt; that is being hovered/focused, then style this &lt;code&gt;a&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Downside
&lt;/h2&gt;

&lt;p&gt;There is a downside to this. If you hover over an element, come off it so you’re not hovering on anything, then hover on another element shortly after, then the background jumps to the first one in between, which looks a bit odd.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final code
&lt;/h2&gt;

&lt;p&gt;Here is the whole code:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/nicm42/embed/LEpgqRd?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>css</category>
    </item>
    <item>
      <title>The scripting media query</title>
      <dc:creator>Nic</dc:creator>
      <pubDate>Sun, 31 Aug 2025 17:02:41 +0000</pubDate>
      <link>https://dev.to/nicm42/the-scripting-media-query-2i7g</link>
      <guid>https://dev.to/nicm42/the-scripting-media-query-2i7g</guid>
      <description>&lt;p&gt;I know there are a lot more media queries out there than the ones I usually use, but this week I used one I’d never come across before.&lt;/p&gt;

&lt;p&gt;The scripting media query checks whether JavaScript is enabled. It has three keywords, although only two of them are useful.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scripting&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="nt"&gt;Javascript&lt;/span&gt; &lt;span class="nt"&gt;is&lt;/span&gt; &lt;span class="nt"&gt;disabled&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scripting&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;initial-only&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="nt"&gt;Javascript&lt;/span&gt; &lt;span class="nt"&gt;is&lt;/span&gt; &lt;span class="nt"&gt;only&lt;/span&gt; &lt;span class="nt"&gt;enabled&lt;/span&gt; &lt;span class="nt"&gt;on&lt;/span&gt; &lt;span class="nt"&gt;page&lt;/span&gt; &lt;span class="nt"&gt;load&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scripting&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="nt"&gt;Javascript&lt;/span&gt; &lt;span class="nt"&gt;is&lt;/span&gt; &lt;span class="nt"&gt;enabled&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(I know CSS doesn’t use // for comments, but actual comments are grey, which I find a very hard colour to read on a black background).&lt;/p&gt;

&lt;p&gt;Interestingly, Tailwind (which was what the project was using) only has the disabled version (with &lt;code&gt;noscript:classHere&lt;/code&gt;), which was unhelpful for me. In my case I had a sticky header which shrinks down on scroll. The shrinking can only be done with JavaScript and without shrinking the header is massive. So if JavaScript is disabled we don’t want a sticky header. Which is easier to do in CSS than Tailwind:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scripting&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nt"&gt;header&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;sticky&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Tailwind I’d have needed to do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;header&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"sticky top-0 noscript:static"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Content here
&lt;span class="nt"&gt;&amp;lt;/header&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>css</category>
      <category>tailwindcss</category>
    </item>
    <item>
      <title>Using ChatGPT</title>
      <dc:creator>Nic</dc:creator>
      <pubDate>Fri, 23 May 2025 18:49:31 +0000</pubDate>
      <link>https://dev.to/nicm42/using-chatgpt-ppp</link>
      <guid>https://dev.to/nicm42/using-chatgpt-ppp</guid>
      <description>&lt;p&gt;This week I had a couple of things I got stuck on and googling/Stack Overflow weren’t helping me much. I know that people have said that AI can help you with programming and I thought I’d see how much help it was getting me unstuck.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem 1
&lt;/h2&gt;

&lt;p&gt;I went a few rounds with it coming up with suggestion that sounded reasonable, but none of them helped. Although I found that telling it exactly what wasn’t working helped me to establish what the problem actually was.&lt;/p&gt;

&lt;p&gt;Sadly, though, it then started giving me code where I couldn’t see what it had changed. When I asked, it told me it had added a function. But that function was already there… At that point it become clear that it wasn’t going to be of any more help and I gave up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem 2
&lt;/h2&gt;

&lt;p&gt;This started similarly, with it coming up with reasonable-sounding explanations and suggestions, none of which solved the problem. And then it started giving me links to CodePens it had created. All of which were empty. When I asked it apologised and gave me a new link. Which was also empty. It did also give me all the code that would be in the CodePen, so it didn’t matter too much.&lt;/p&gt;

&lt;p&gt;But since we weren’t solving the problem I asked it where it had got its answers from. It initially refused to give me any links until I persisted. And then it gave me StackOverflow links to completely different problems in completely different languages…&lt;/p&gt;

&lt;p&gt;When I called it on that it told me what to search for on StackOverflow (and how to search StackOverflow). They were reasonable search strings, even if they didn’t lead to to anything I hadn’t already come across.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;If I was merely judging it on those two interactions then I’d say it was completely useless. Plus every time it gives an answer it started by telling me I was right which got grating after a while. But I already knew it did that sort of thing and can’t be turned off. I also hate that it shows you its answer one line at a time, but I’d already asked it about that and it also can’t be turned off.&lt;/p&gt;

&lt;p&gt;So it’s annoying, but I’m not totally giving up on it. I have heard from people that it can be good for giving you starter code that you can improve on. And there may be less complex problems that it will be better at finding answers for.&lt;/p&gt;

&lt;p&gt;I also only tried ChatGPT - it may be that some of the others are less annoying and/or more useful.&lt;/p&gt;

</description>
      <category>ai</category>
    </item>
    <item>
      <title>Select keyboard controls</title>
      <dc:creator>Nic</dc:creator>
      <pubDate>Fri, 18 Apr 2025 16:03:38 +0000</pubDate>
      <link>https://dev.to/nicm42/select-keyboard-controls-4fek</link>
      <guid>https://dev.to/nicm42/select-keyboard-controls-4fek</guid>
      <description>&lt;p&gt;I was recently given a design that included a customised select. Since that’s currently only available in the most recent version of Chrome, I went looking for libraries and instructions on how to create your own select. And I came across a problem: none of them talked about the keyboard controls in a way that matched with how select works for me with the keyboard. Until I considered that I was using Firefox and most people use Chrome. Turns out they don’t work identically. So I went through the main browsers and documented what did what.&lt;/p&gt;

&lt;h2&gt;
  
  
  Same for all browsers
&lt;/h2&gt;

&lt;p&gt;Most keyboard controls are the same in all browsers.&lt;/p&gt;

&lt;h3&gt;
  
  
  When select is closed:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Enter&lt;/strong&gt;: does nothing&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Space&lt;/strong&gt;: opens select&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Tab&lt;/strong&gt;: goes to next tabbable element&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Shift + tab&lt;/strong&gt;: goes to previous tabbable element&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Down arrow&lt;/strong&gt;: opens select&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Up arrow&lt;/strong&gt;: opens select&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Any letter key&lt;/strong&gt;: selects first/next option that starts with that letter&lt;/p&gt;

&lt;h3&gt;
  
  
  When select is open:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Enter&lt;/strong&gt;: selects focused option and closes select&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Escape&lt;/strong&gt;: closes select&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Down arrow&lt;/strong&gt;: focuses next option&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Up arrow&lt;/strong&gt;: focuses previous option&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Home&lt;/strong&gt;: focuses option at top of list&lt;br&gt;&lt;br&gt;
&lt;strong&gt;End&lt;/strong&gt;: focuses option at bottom of list&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Any letter key&lt;/strong&gt;: selects first/next option that starts with that letter&lt;/p&gt;

&lt;h2&gt;
  
  
  Different in different browsers
&lt;/h2&gt;

&lt;p&gt;I tested in Firefox, Chrome, Safari and Opera, all on a Mac. Although a Mac has different keyboard shortcuts to Windows and Linux, navigating a website doesn’t seem to be any different on a Mac.&lt;/p&gt;

&lt;h3&gt;
  
  
  When select is closed
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Escape&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Firefox: goes to next tabbable element&lt;br&gt;&lt;br&gt;
The rest: does nothing&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Page down&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Firefox: selects option one page down&lt;br&gt;&lt;br&gt;
The rest: does nothing&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Page up&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Firefox: selects option one page up&lt;br&gt;&lt;br&gt;
The rest: does nothing&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Home&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Firefox: selects option at top of list&lt;br&gt;&lt;br&gt;
The rest: does nothing&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;End&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Firefox: selects option at bottom of list&lt;br&gt;&lt;br&gt;
The rest: does nothing&lt;/p&gt;

&lt;h3&gt;
  
  
  When select is open
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Space&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Firefox: does nothing&lt;br&gt;&lt;br&gt;
The rest: selects focused option and closes select&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tab&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Firefox: selects focused option and closes select&lt;br&gt;&lt;br&gt;
The rest: selects random option&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Shift + tab&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Firefox: selects focused option and closes select&lt;br&gt;&lt;br&gt;
The rest: selects random option&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Page down&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Firefox: focuses option one page down&lt;br&gt;&lt;br&gt;
The rest: focuses option at bottom of list&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Page up&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Firefox: focuses option one page up&lt;br&gt;&lt;br&gt;
The rest: focuses option at top of list&lt;/p&gt;

</description>
      <category>a11y</category>
    </item>
    <item>
      <title>Accessible toggle</title>
      <dc:creator>Nic</dc:creator>
      <pubDate>Wed, 12 Feb 2025 19:33:23 +0000</pubDate>
      <link>https://dev.to/nicm42/accessible-toggle-397i</link>
      <guid>https://dev.to/nicm42/accessible-toggle-397i</guid>
      <description>&lt;p&gt;I recently got given a design that included a toggle. But I know they are not the most accessible of components, so I had to do some research on the best ways to create them.&lt;/p&gt;

&lt;p&gt;I started at &lt;a href="https://www.w3.org/WAI/ARIA/apg/patterns/switch/" rel="noopener noreferrer"&gt;https://www.w3.org/WAI/ARIA/apg/patterns/switch/&lt;/a&gt;. This site is really useful for telling you how custom components should behave and what things you need to make sure to include. And it has examples.&lt;/p&gt;

&lt;p&gt;I went with the checkbox example, since the one I had to create had an on and an off state. In my case, the design had labels on either side of the toggle and the on one would show when the toggle was on and the off one when the toggle was off.&lt;/p&gt;

&lt;h2&gt;
  
  
  HTML
&lt;/h2&gt;

&lt;p&gt;My HTML ended up like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"sr-only"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;What this toggle is for&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;aria-hidden=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"off"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Off&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"switch"&lt;/span&gt; &lt;span class="na"&gt;checked&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"toggle"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"toggle-button"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;aria-hidden=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"on"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;On&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All of the content is inside the label, so the whole thing is clickable. As with any input we need a label. The design doesn’t include one, so we need to include a span with the label and hide it from sighted users.&lt;/p&gt;

&lt;p&gt;The checkbox is doing the actual work and the &lt;code&gt;.toggle&lt;/code&gt; and &lt;code&gt;.toggle-button&lt;/code&gt; make up the actual toggle. In the design I had the checkbox should be on by default, hence why the HTML includes the &lt;code&gt;checked&lt;/code&gt; attribute.&lt;/p&gt;

&lt;p&gt;Then there’s the on/off texts, which are hidden from screen readers. This is because the screen reader will announce whether the checkbox is on or off. The toggle is really only an interesting way to show a checkbox to sighted users.&lt;/p&gt;

&lt;h2&gt;
  
  
  CSS
&lt;/h2&gt;

&lt;p&gt;For the layout, I used a grid to put the elements all next to each other and add some code to change the opacity of the on/off texts based on the checkbox’s state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;label&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;inline-grid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;grid-template-columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.off&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;opacity&lt;/span&gt; &lt;span class="m"&gt;250ms&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.on&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;opacity&lt;/span&gt; &lt;span class="m"&gt;250ms&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.checkbox&lt;/span&gt;&lt;span class="nd"&gt;:checked&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt; &lt;span class="nc"&gt;.on&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.off&lt;/span&gt;&lt;span class="nd"&gt;:has&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt; &lt;span class="nc"&gt;.checkbox&lt;/span&gt;&lt;span class="nd"&gt;:checked&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;:has&lt;/code&gt; is useful here as a previous sibling selector. Although if it didn’t exist, we could just put the off text after the checkbox in the HTML and re-order the elements. Usually that would be a terrible idea, but in this case, they’re only there for sighted users and aren’t selectable, so it’s not going to make much difference.&lt;/p&gt;

&lt;p&gt;And then there’s the toggle itself. I remembered last year hearing a talk from Sara Soueidan about hiding the default checkbox when you’re styling your own. Handily she also has a blog post about it at &lt;a href="https://www.sarasoueidan.com/blog/inclusively-hiding-and-styling-checkboxes-and-radio-buttons/" rel="noopener noreferrer"&gt;https://www.sarasoueidan.com/blog/inclusively-hiding-and-styling-checkboxes-and-radio-buttons/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The important part of this post is that on Android you can explore a page by touch and feel interactive elements. Which means we can’t hide the checkbox by making it tiny or moving it off the page.&lt;/p&gt;

&lt;p&gt;What we are doing instead is making the checkbox and toggle the same size and putting the toggle on top of the checkbox (and also adding some styling to make it look pretty).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--toggle-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;52px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--toggle-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--toggle-button-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;26px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.checkbox&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--toggle-width&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--toggle-height&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;grid-column-start&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.toggle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--toggle-width&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--toggle-height&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.125rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;lightgrey&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.toggle-button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--toggle-button-width&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;aspect-ratio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;left&lt;/span&gt; &lt;span class="m"&gt;250ms&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.checkbox&lt;/span&gt;&lt;span class="nd"&gt;:focus-visible&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;.toggle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;outline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="no"&gt;black&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;outline-offset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using custom properties makes sure that the checkbox and toggle are the same size. And because this is in a grid we can make sure that the absolutely positioned checkbox is in the same grid column as the checkbox.&lt;/p&gt;

&lt;p&gt;Although the checkbox is turned on by default, the CSS defaults to the checkbox being turned off. All we have left is to move the toggle button over the right and change the toggle’s colour when the checkbox is checked:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.checkbox&lt;/span&gt;&lt;span class="nd"&gt;:checked&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;.toggle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;red&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.checkbox&lt;/span&gt;&lt;span class="nd"&gt;:checked&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;.toggle&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;.toggle-button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--toggle-button-width&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;-&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Final result
&lt;/h2&gt;

&lt;p&gt;And it ends up looking like a standard toggle:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/nicm42/embed/NPWKgqm?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>css</category>
    </item>
    <item>
      <title>Review of 2024</title>
      <dc:creator>Nic</dc:creator>
      <pubDate>Tue, 31 Dec 2024 16:59:19 +0000</pubDate>
      <link>https://dev.to/nicm42/review-of-2024-14k3</link>
      <guid>https://dev.to/nicm42/review-of-2024-14k3</guid>
      <description>&lt;p&gt;2024 had a lot going on. Just not so much in anything I blogged about or side projects I created.&lt;/p&gt;

&lt;p&gt;I spent January looking for jobs. There was a surge in the number posted in comparison to December, and I had to do take-home tests, which took up time.&lt;/p&gt;

&lt;p&gt;In March I started a new job and in June I got made redundant from it. Its a familiar tale, but its reading other peoples stories about getting made redundant that make me realise just how lucky I got to be starting a new job a month later.&lt;/p&gt;

&lt;p&gt;It was one of the few jobs I heard back from, and the only one who offered me an interview. Fortunately they offered me the job and it was one that I wanted.&lt;/p&gt;

&lt;p&gt;What its meant that any public activity has felt like its all about getting a job and not about me getting to have fun. Which is annoying because there's a side project Id really like to do that would actually be useful to me. Im hoping to do it in 2025!&lt;/p&gt;

&lt;p&gt;In a years time Id also like to still be employed with the same company, but I don't have 100% control over that (and if someone offered me a 6 figure salary to play with bunnies/kittens/read books all day I wouldn't say no).&lt;/p&gt;

</description>
      <category>blogging</category>
    </item>
    <item>
      <title>Button type button</title>
      <dc:creator>Nic</dc:creator>
      <pubDate>Sun, 24 Nov 2024 08:57:02 +0000</pubDate>
      <link>https://dev.to/nicm42/button-type-button-27h6</link>
      <guid>https://dev.to/nicm42/button-type-button-27h6</guid>
      <description>&lt;p&gt;Ive seen &lt;code&gt;&amp;lt;button type=button&amp;gt;&lt;/code&gt; before but thought that you never need it. Turns out you do&lt;/p&gt;

&lt;p&gt;If you have a button on the page then by default its type is button.&lt;/p&gt;

&lt;p&gt;But if that button is inside a form then by default its type is submit.&lt;/p&gt;

&lt;p&gt;It makes sense. A button outside of a form with a type of submit wouldn't make sense: what would it submit? Same with reset. So it makes sense that the only thing the button can do is to be a button. But if you have a form the most likely thing that button will do is to submit the form (the second most likely is to reset the form).&lt;/p&gt;

&lt;p&gt;So if your form contains a button that doesn't submit or reset the form (as I had recently), it needs to be of type button.&lt;/p&gt;

</description>
      <category>html</category>
    </item>
    <item>
      <title>CSS is important (or should that be !important?)</title>
      <dc:creator>Nic</dc:creator>
      <pubDate>Sun, 10 Nov 2024 17:52:27 +0000</pubDate>
      <link>https://dev.to/nicm42/css-is-important-or-should-that-be-important-4418</link>
      <guid>https://dev.to/nicm42/css-is-important-or-should-that-be-important-4418</guid>
      <description>&lt;p&gt;It can be depressing sometimes on the internet reading full stack and backend developers thinking that CSS is easy. Anyone can just bung something in and it'll be fine. As a front end developer it makes me wonder what the point of me is.&lt;/p&gt;

&lt;p&gt;The thing is, CSS isn't easy. You cant just bung something in and hope for the best. Ive seen that this year in CMS plugins that you pay for that have terrible CSS.&lt;/p&gt;

&lt;p&gt;There are a lot of floats going on, which feels outdated. Who uses floats for layouts these days? There also doesn't feel like a lot of testing going on. It might look ok, but then fail when you resize the browser. They've written it assuming that the size of the browser on load is the size it will always be. But on a mobile or tablet you might turn it round. On a computer you might maximise your browser window - or make it smaller.&lt;/p&gt;

&lt;p&gt;That's the thing with working on the front end: users could do anything. Its our job to anticipate that and test for it. Front end developers are useful after all!&lt;/p&gt;

</description>
      <category>frontend</category>
    </item>
    <item>
      <title>A formative experience</title>
      <dc:creator>Nic</dc:creator>
      <pubDate>Mon, 23 Sep 2024 17:31:24 +0000</pubDate>
      <link>https://dev.to/nicm42/a-formative-experience-1g63</link>
      <guid>https://dev.to/nicm42/a-formative-experience-1g63</guid>
      <description>&lt;p&gt;I was talking to a friend recently about going to university and discovering the internet properly for the first time. We both used it do something we now do a lot.&lt;/p&gt;

&lt;p&gt;The Windows computers had the first four versions of Netscape Navigator on them (the big browser at the time). I used them to see what websites worked in each of them. From what I remember, most things worked in the last three and hardly anything worked in the first one. Frames certainly didn't and that was the big trend of the time.&lt;/p&gt;

&lt;p&gt;At the time I had no idea it was the sort of thing you could get a job in. And now I get paid to do that sort of thing.&lt;/p&gt;

</description>
      <category>webdev</category>
    </item>
  </channel>
</rss>
