More from HTMHell
button table { margin: 0; } .fa-arrow-left::before {content:"←"} Bad code <button type="button" onclick="window.open('https://example.com/other-page')"> <table> <tbody> <tr> <td> <i class="fa fa-arrow-left" aria-hidden="true"></i> </td> <td align="left">Back</td> </tr> </tbody> </table> </button> Back Issues and how to fix them The HTML isn't valid because the table element isn't allowed as a child of the button element. Based on the content categories listed on MDN, the table element qualifies as flow content and can only be placed inside an element that expects flow content. The button element, on the other hand, expects phrasing content, not flow content. The semantic information of the table doesn't cause any issues because the button's content is presentational See Buttons Role on W3C, Presentational Children. Keep it simple and structure the button element using CSS, such as Flexbox. Instead of using tables to structure the button element, use phrasing content elements, such as span, img, or SVG. Good code <button type="button" onclick="alert('Hello World!')"> Back </button> Resources <button> on MDN <table> on MDN Content categories on MDN Buttons Role on W3C <button> on W3Schools <table> on W3Schools Presentational Children
by Rian Rietveld It's a common pattern to use a logo in the header as a link to the homepage. Fun fact: the alt text of the image inside a link, will be added to the link text. The problem with linking a logo is that it serves 2 purposes: a logo, that tells you which site you are visiting; a link, that leads to the homepage. So add both that info in the alt text. Explain what's on the image and where the link leads to: "Site name logo, to the homepage". Note: Start the alt text with the visible text, then the link will be easier to target for people using voice recognition software. Let's take as example the logo of my home town Leidschendam-Voorburg. In code (simplified): <a href="/"> <img alt="Leidschendam-Voorburg logo, to the homepage" src="logo-lv.svg" /> </a> Generated HTML: VoiceOver in Safari will announce this as: All info is there. There is an advantage of using the alt text instead of an aria-label solution. When the connection is slow, the alt text will show up before the image does and already informs all users of the site name and link destination. It's quite robust. Discussion Do I need the word logo? Isn't that redundant, like the word image or picture? Yes, in this case the fact that this is a logo tells important info. Not only for blind users, but for all screenreader users. If you are visually impaired but not totally blind, you may see the image vaguely. With the addition of the word logo, you also know what the image is. The site name is required, but the logo gives extra context. Isn't this a violation of 2.5.3 Label in Name? No, the visible name is in the alt text, which becomes the accessible name of the link. Adding extra context to the link is common practice. Compare this with the notorious "Read more" link in a card. A common pattern is to use a sr-only CSS class (or equivalent) with additional text: <a href="url">Read more<span class="sr-only"> about cute kitten</span></a> . You see Read more. You hear Read more about cute kitten. In our case: You see the site name and logo; the visual position tells the link destination. You hear the site name, the fact it's a logo and the link destination. The whole visible text should be in the accessible name, but extra information, like the meaning of the image and link destination can be added for context. That way the purpose of the link is explained. Why didn't you use an aria-label? Of course there are other and also valid solutions. By using plain simple HTML I want to honor the first rule of ARIA: If you can use a native HTML element or attribute with the semantics and behavior you require already built in, instead of re-purposing an element and adding an ARIA role, state or property to make it accessible, then do so. Happy Holidays!
Bad code <button type="button" onclick="window.open('https://example.com/other-page')">Link target description</button> Issues and how to fix them A button opening a link will be unexpected behavior for screen reader users. No matter how it is styled. Links disguised as buttons won’t show up in the link list of a site in assistive technologies. Use links for navigation to other pages or sections, and buttons for actions performed on the current page or within the application. Good code <a href="https://example.com/other-page">Link target description</a> Resources ` on MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a) - [`` on MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button) - [Buttons vs. Links by Eric Eggert](https://yatil.net/blog/buttons-vs-links)
The good intentions were there but in the HTML and Accessibility world, less is sometimes more. Bad code <label for="textinput">First name</label> <input type="text" id="textinput" aria-label="First name" placeholder="First name" title="First name"> Issues and how to fix them The aria-label, placeholder, and title attributes all provide the same informaton ("First name"), leading to the screenreader reading the same text multiple times. The aria-label is unnecessary since the input is already correctly labeled by the <label> element. <label> elements should be preferred to aria-label since they are also visible to sighted users. The title attribute is not needed here, as the label and placeholder already convey the necessary information. Using title in this context adds unnecessary complexity. The placeholder text should provide a hint / example to the user what kind of input is expected, it should not act as a label or contain the same content. Good code <label for="textinput">First name</label> <input type="text" id="textinput"> Resources <label> on MDN aria-label on MDN placeholder on MDN title on MDN
More in programming
I listen to a lot of podcasts, and I like how they fit around other tasks. I press play, lock my phone, and put it down. I’m free to wash the dishes, fold the laundry, or shop for groceries. Unfortunately, more and more information is only published as a video. Technical talks, conference sessions, video essays – they don’t work in an audio-only podcast app. I could convert these videos to MP3 files, but that breaks down the moment a video isn’t pure spoken word. If a speaker says, “Look at this slide” or holds up a diagram, an audio-only file leaves me stranded. I don’t want to give up the podcast player I like, nor stare at a screen for an hour – but I do want the information in these videos. To solve this, I’m abusing my podcast player’s chapter support. This gives me the best of both worlds: I can listen to a video as audio-first, and glance at my lock screen if I need a moment of visual context. The idea: Chapters every few seconds MP3 files can have ID3 metadata, and ID3 metadata can include chapters. A chapter covers a particular time range, and it can have an associated title, description, and cover art. My podcast app of choice is Overcast, which can’t play videos, but it does have robust chapter support. I can jump between chapters, navigate a table of contents, and see per-chapter cover art. To get videos into Overcast, I’m creating MP3 files with a new chapter every few seconds, and the per-chapter cover art is a corresponding frame from the video. As I play the file, I get a slow, stop-motion-like rendition of the original video. If my phone is locked, I can glance at my lock screen and see the current frame in the Now Playing screen. Overcast is developed by Marco Arment, and I got this idea from Forecast, his app for adding chapters to podcasts. In particular, I was struck by its ability to create chapters that don’t display in the chapter list – ideal if I don’t want a table of contents with hundreds of entries. As I was developing my script, I compared my output to the output from Forecast to ensure I was creating the chapters correctly. The code: FFmpeg and Mutagen There are three steps in this process: Convert a video file to an MP3 Extract images from the video at a fixed interval Insert the images as hidden chapters in the MP3 file Let’s go through each in turn. 1. Convert a video file to an MP3 Converting a video file to an MP3 is a single FFmpeg command: ffmpeg -i video.mp4 audio.mp3 This is consistently the slowest step of the process, and I do wonder if I could use different settings or an alternative encoder to make it go faster – but it’s not slow enough to be worth further investigation. 2. Extract images from the video at a fixed interval Extracting images from a video needs a more complicated FFmpeg command: ffmpeg -i video.mp4 \ -vf 'fps=1/5,scale=iw*sar:ih,scale=min(iw\,945):min(ih\,945):force_original_aspect_ratio=decrease' \ thumbnail_%04d.jpg This extracts an image every 5 seconds, downscales any image larger than 945 pixels square (while preserving the original aspect ratio), and saves the results as sequentially numbered JPEG images (thumbnail_0001.png, thumbnail_0002.png, and so on). The key is the -vf flag, which defines two FFmpeg filters: The fps filter selects one frame every 5 seconds (fps=1/5). The first scale filter scales the width based on the sample aspect ratio (scale=iw*sar:ih). Without this filter, frames can be stretched and distorted. The second scale filter scales the input video, preserving the original aspect ratio (force_original_aspect_ratio=decrease), and ensuring the output images fit within 945×945px or the size of the input video, whichever is smaller. My limit is 945 pixels because that’s the largest size that cover art is shown on my iPhone. This filter still isn’t completely correct – it sometimes creates images from portrait videos that are smaller than I’m expecting – but it’s good enough. These are only thumbnails for glancing at, and if I want to change it later, I can always do the image resizing outside FFmpeg. 3. Insert the images as hidden chapters in the MP3 file Inserting the chapters into the MP3 file is more complicated. Although FFmpeg has basic support for ID3 metadata, as far as I know, it can’t insert chapters with per-chapter artwork. Instead, I’m going to reach for Python and the Mutagen library. Here’s the code to add a chapter to an MP3 file: from mutagen.id3 import APIC, CHAP, ID3, PictureType audio = ID3("audio.mp3") with open("thumbnail_0001.jpg", "rb") as f: img_data = f.read() image_frame = APIC(mime="image/jpeg", type=PictureType.OTHER, data=img_data) chapter_frame = CHAP( element_id="chp1", start_time=0, end_time=5 * 1000, sub_frames=[image_frame] ) audio.add(chapter_frame) audio.save() This creates a single chapter that lasts the first 5 seconds (0 to 5000 milliseconds), and the per-chapter cover art is thumbnail_0001.jpg. If we ran this in a loop, we could add images for every 5 second slice of the original video. This code is inserting two frames into the ID3 metadata: The CHAP (chapter) frame contains the timing information, and it can have subframes for metadata like title, chapter art, or associated URL. The APIC (attached picture) subframe contains information about a picture, which can either be a blob of image data or a URL to an image on the web. Normally, you’d also insert a CTOC frame which defines a table of contents, but I don’t want a TOC with hundreds of 5-second chapters, so I’m deliberately not doing this here. This is allowed by the ID3 spec – you’re not required to insert a CTOC frame if you’re using chapters, and you can have chapters that aren’t listed in your table of contents. To work out which frames I needed, I used Forecast to create some chapters by hand, and I inspected their frames. In particular, loading an MP3 and calling Mutagen’s pprint() method shows a human-readable list of frames, and then I could drill into the individual fields: from mutagen.id3 import ID3 audio = ID3("audio.mp3") print(audio.pprint()) I wrapped all this code in a project called glancecast, which allows you to convert a video file with a single command, with optional flags to set the frame length and chapter art size: $ python3 glancecast.py interesting_talk.mp4 interesting_talk.mp3 The process takes a minute or so to complete, most of which is spent transcoding the video file to MP3. The resulting MP3s are usually 40 to 50 MB in size, which is very reasonable. The outcome: How it looks in practice Here’s what one of these “glanceable” podcasts looks like in Overcast and on my lock screen: Maggie Appleton presented this talk over two years ago and it’s been on my “talks to watch” list ever since. Once I put it in Overcast? I listened to it in less than a day. It’s not a lot of extra information, but enough that I can quickly glance down and get the gist of what a speaker is saying. Both views update with a new frame every few seconds, or I can put my phone in my pocket and ignore the screen. I’ve used this approach for half a dozen videos so far, and I’m happy with the results. I expect to keep using it, because I have a long queue of videos I’ve been meaning to watch. If you’d like to try this, check out glancecast for the full code and instructions. [If the formatting of this post looks odd in your feed reader, visit the original article]
Andrew Baker, the current Group CIO at Capitec Bank wrote an interesting piece on AI and open source, and how these tools that generate code according to one’s specification may replace the general reliance on open source implementations done by contributors around the world. I’d really recommend reading it. I have great admiration and respectContinue reading "AI Isn’t Replacing Open Source"
I've mostly given up keeping up with agent trends. Every few months, I ignore all of it and ask what I'm actually getting use out of. Three things…
A framework for thinking about when AI involvement is additive or a violation
Why we need richer, thicker interfaces and better boundary objects for collaborative planning with agents