Christian Heilmann

You are currently browsing the archives for the General category.

Archive for the ‘General’ Category

Seven ways to test for accessibility of your web site with browser Developer Tools

Monday, January 11th, 2021

There are lots of ways to test your web site for accessibility issues. Services, software packages, even human testing companies. They all have their place and often a test with real people is the best thing to do. However, for a quick, preliminary test you don’t need to install anything or pay for a service. Browsers come with developer tools built-in and these have great accessibility testing features. Here’s a list of the ones in the Developer Tools of browsers like Microsoft Edge and Google Chrome:

Issues Panel

The issues panel shows all kind of problems with the current web page. You can either open it directly or click the issues icon top right (the blue speech bubble). Issues are also announced in the Console.

In the panel you then navigate to the “Accessibility” section and can see if there are any problems. Each reported issue comes with an explanation what is wrong and why and a link to the parts of the developer tools where you can inspect and fix the problem.

The issues panel is powered by Webhint, a service that checks for all kind of problems (and NPM package in case you want to use it in your CI/CD workflow).

Issues Panel with accessibility parts highlighted

Element picker with accessibility info overlay

Information shown in the elements overlay

When you have the developer tools open, you can use the element picker tool to highlight and inspect parts of the page. The overlay shows all kind of information:

  • The type of HTML element and class/ID information
  • The dimensions of the element
  • The Text colour
  • The Font used
  • Margin information

In addition to that you also get accessibility information

  • The contrast ratio of foreground to background – if there is enough contrast you can see a green checkmark, otherwise a red exclamation icon
  • The name as announced to assistive technologies like screenreaders
  • The ARIA role
  • An indicator if the element is keyboard focusable or not (either a green checkmark or a grey circle with a line through it)

This information should get you pretty far. Once you found an element with not enough colour contrast you can use the colour picker to fix it.

Colour Picker with contrast check

Once you recognised that some colours on your page have contrast problems, you can use the colour picker of the elements tool to see how to fix them. You open the colour picker by clicking on any of the colour swatches in the CSS of the element.

Picking a colour from the styles pane

In the colour picker you get a section showing the contrast ratio and whether it is compliant with AA or AAA web guidelines or not. For colours that don’t have enough contrast the picker also suggests colours that are compliant. To pick those, just click on the colour swatches.

Colour picker showing possible colours with enough contrast

The colour picker also shows two lines over the colour selection box that indicate AA or AAA compliance. That way you can see if quickly if your desired colour falls into any of those sections.

However, there is an issue with this algorithm as it doesn’t take into consideration the font weight of a certain font but only the contrast ratio of foreground and background colour. A lightweight font with enough contrast may yet be unreadable. This is why the current contrast algorithm will soon be replaced by one that takes this into consideration and you can turn the new one on in the developer tools settings.

Turning on the new contrast algorithm

Once you turned the experiment on and reloaded developer tools, the colour picker contrast section looks different and only shows one line for valid colours.

The colour picker with the new contrast options showing only one line in the colour field

Vision Deficit Emulation

The way you perceive your web site isn’t how the world perceives it. This is why we added an option to emulate different vision deficiencies. Using this feature in the rendering pane of the developer tools you can see what your product looks like for different users:

Simulating different visual deficiencies using devtools

  • Blurred vision – The user has difficulty focusing on fine details.
  • Protanopia – The user is unable to perceive any red light.
  • Deuteranopia – The user is unable to perceive any green light.
  • Tritanopia – The user is unable to perceive any blue light.
  • Achromatopsia – The user is unable to perceive any color, which reduces all color to a shade of grey.

Choose from one of the options and the site will automatically change colours.

Showing fruit pictures with simulated colour deficits

Rendering Emulation (dark, light, high contrast, reduced motion)

The rendering view also has a few features to simulate different operating system settings. One of them is to simulate reduced motion which is great to ensure that your animations are not shown to users that don’t want or can’t cope with animations on the web.

You can also switch from dark to light mode without having to change the settings of your computer.

Soon you will also be able to simulate high contrast mode without having to change your operating system. I’ll blog more about this soon.

Reddit in simulated forced colour mode

Accessibility Tree

The accessibility pane of the developer tools also shows the accessibility tree of the document. This is different to what you see in the elements pane but is what assistive technology gets about your document. Using the accessibility tree you can check if an element is announced the way it should be to, for example, screen readers.

Source Order Viewer (experimental)

Using CSS you can change the order of elements how they appear on the screen. This change, however, is not part of the source code of the document and thus will not be announced by assistive technology like screen readers. By using the Source Order Viewer the developer tools will overlay the order number of each element in the browser and you can see if they are not only shown visually close to another but also for non-sighted users or search engines.

Source order viewer overlaying the order on HTML elements to show problems in the reading order

More to come

We are constantly working on improving the accessibility tooling in the developer tools and are open to feedback. Feel free to contact me or talk to @EdgeDevTools on Twitter.

Back to basics: adding a playback speed control to an audio player

Monday, December 28th, 2020

Currently I am publishing the new Developer Advocacy Handbook chapter by chapter and I also started recording audio versions of each chapter. A common request of people is to be able to control the speed of a audio/video recording. Luckily enough, using basic HTML5 and JavaScript, this is not that hard to achieve, so let’s do it.

You can see and hear the result in the following video:

You can check the final version on Codepen

See the Pen
Audio with speed control
by Christian Heilmann (@codepo8)
on CodePen.

The best start is always sensible HTML.

<div class="speedcontrolcontainer">
  <audio src="https://file-examp…xample_MP3_2MG.mp3" controls></audio>
    <label for="pbrate">Speed:</label>
    <input type="range" id="pbrate" min=.5 max=3 value=1 step=.1>

In this case, using the audio element with a controls attribute already gives us a play button, a scrubber, time display, volume and an overflow menu with download option. For the speed control, we need a slider with a label to keep it accessible and a span element to show the current value of the playback speed. The range control is good for this as it also gives us keyboard access and allows us to limit the speeds we want to allow. In this case, from half speed to four times the speed.

Let’s only go into basic CSS for styling here:

.scc {
  max-width: 30em;
  display: block;
  border: 1px solid #000;
  padding: 10px;
  font-family: Sans-serif;
.scc audio { 
  width: 100%; display: block; 
.scc div {
  display: flex;
  padding: .5em 0;
  gap: 5px;
.scc label { flex: 1; }
.scc input[type="range"] { flex: 5; }
.scc span {
  flex: 1;
  text-align: center;

We give the control a container element and set it to a max-width of 30em. We display the audio element as block and make it use up all the available space. We give the new speed control a bit of padding and use flexbox to lay it out.

The last bit is to use JavaScript to create the rest of the functionality:

const audio = document.querySelector('.scc  audio');
const playbackrate = document.querySelector('.scc input');
const display = document.querySelector('.scc span');
const displayvalue = val => {
  return parseInt(val * 100, 10) + '%'
display.innerText = displayvalue(audio.playbackRate);
playbackrate.addEventListener('change', e => {
  audio.playbackRate = playbackrate.value;
  display.innerText = displayvalue(playbackrate.value);

  • We get references to the audio element, the slider and the span we want to display the current value of the slide in.
  • As the playback speed in the audio API is a number, we need to convert it to a percentage. This is what the displayvalue method does for us.
  • We display the current playbackRate of the audio element in the span next to the slider.
  • We apply an event Listener to the input element that fires every time it changed.
  • When there is a change, we set the playbackRate of the audio element to the value of the slider
  • And we display the percentage in the span

One thing that is missing is that users may want to have their favourite speed stored so they don’t have to set it again chapter by chapter. To do this, we can use localStorage, set the playbackRate and value when we load the document and store it when the slider changed.

const audio = document.querySelector('.scc  audio');
const playbackrate = document.querySelector('.scc input');
const display = document.querySelector('.scc span');
const displayvalue = val => {
  return parseInt(val * 100, 10) + '%'
if (window.localStorage.pbspeed) {
  audio.playbackRate = window.localStorage.pbspeed;
  playbackrate.value = window.localStorage.pbspeed;
display.innerText = displayvalue(audio.playbackRate);
playbackrate.addEventListener('change', e => {
  audio.playbackRate = playbackrate.value;
  display.innerText = displayvalue(playbackrate.value);
  window.localStorage.pbspeed = playbackrate.value;

And that’s it! An audio playback control with playback speed option.

The new and improved Developer Advocacy Handbook is out – Read Chapters 1 & 2 now

Thursday, December 17th, 2020

Eleven years ago I wrote the Developer Evangelism Handbook and since then it helped a lot of of people start a career in Developer Relations. Now a publisher approached me if they could do a print version. The negotiations are still underway, but I was sure that it is not a good plan to release the book in the state it is in. So I spent the last few days cleaning up. I edited the chapters and removed outdated examples or links to defunct products. And I added new content that is more relevant to today’s world of developer advocacy. I will release chapters bit by bit over the next weeks. Once all is live I will open the GitHub repository for contribution and feedback.

For now, head over to and start with chapter one and two.

The book showing in the browser

You can see the whole Table of Contents and the chapters will light up as they become available.

I wrote the new book in Markdown and I am using GitHub Pages to publish and host it. It was a fun exercise to learn Jekyll and I am still in the middle of it. The book has an automatic dark/light theme detection and should be nice to read across all kind of form factors. Once done, I will also add a serviceworker and such to make the book installable. I am also considering generating an ebook version if you are interested.

Quick Tip: How to capture and replace newlines in liquid for Jekyll/GitHub Pages

Thursday, December 17th, 2020

As part of the re-write of The Developer Advocacy Handbook I needed to have blockquotes with different classes.

Fact display in the book

With GitHub Pages markdown you can do that using the > notation:

> **Fact:** There are no bad students or a bad audience --
only bad workshops and talks. Your mood, dedication and
enthusiasm do become those of the audience -- 
if you are not happy, they won\'t be happy.

The problem was that I couldn’t add CSS classes to the blockquote elements so I can show them in different styles. I wanted four of them: example, fact, warning and tip.

The good news is that even without any styling using the strong name should make it obvious. But as there is no text “contains” selector in CSS I couldn’t rely on that to change the blockquote element.

First solution: JavaScript

The first thing I thought was to use JavaScript to apply the classes, which is pretty straight forward:

let bqs = document.querySelectorAll('blockquote');
  bqs.forEach(b => {
  b.className = b.

This, however, felt dirty and I wanted to use the system itself to do that task.

Moving to liquid

So I wrote a liquid include to convert the HTML before rendering. In my layout template, this works by replacing the {{ content }} with {% include blockquotes.html html=content %}.

In the blockquotes.html, I thought it’d be easy to do a search and replace. Alas, there is the issue that liquid only does string replacement and doesn’t know any regular expressions.

The HTML generated from the markdown has a line-break in it:

  <p><strong>Fact:</strong> There are no bad students … </p>

This is where it didn’t get fun. The replace filter doesn’t allow you to concatenate strings and doesn’t know the concept of n. So, I tried to use the newline_to_br together with strip_newlines filters and then replace the br but it was messy.

Turns out, the main trick was to capture a newline in liquid and assemble the string to replace using that one.

{% capture newline %}
{% endcapture %}
{% capture tip %}<blockquote>{{newline}}  <p><strong>Tip:</strong>{% endcapture%}
{% capture example %}<blockquote>{{newline}}  <p><strong>Example:</strong>{% endcapture%}
{% capture warning %}<blockquote>{{newline}}  <p><strong>Warning:</strong>{% endcapture%}
{% capture fact %}<blockquote>{{newline}}  <p><strong>Fact:</strong>{% endcapture%}
{% assign newhtml = include.html | 
  replace: tip, '<blockquote class="tip"><p><strong>Tip:</strong>' |
  replace: example, '<blockquote class="example"><p><strong>Example:</strong>' |
  replace: warning, '<blockquote class="warning"><p><strong>Warning:</strong>' |
  replace: fact, '<blockquote class="fact"><p><strong>Fact:</strong>' 
{{ newhtml }}

This works fine. Seems superfluous, but it is a way. It might be that there is a much simpler way as I am new to this world, having used PHP before the build the old version of the book. Got a better option? Tell me :)

Update to the Developer Evangelism/Advocacy handbook almost complete

Tuesday, December 15th, 2020

Writing Setup

Eleven years ago I wrote the Developer Evangelism Handbook .Last month I was approached by a publisher who is interested to print it in another language. Whilst flattered, I also couldn’t let that happen as there are parts of the book that are quaintly outdated now. Some of the products I promote aren’t available any longer and there are big differences in the way we use social media and the web now compared to 2009.

So I spent a few evenings polishing the book, removing a lot of outdated material and adding new things that are more relevant now.

I added materials about virtual conference participation, code hosting, recording your own videos and screencasts, and incorporated some of the posts and materials I created since first publication. Currently it is at roughly 40000 words and the letter sized Word Doc would me 85 pages.

For now, I will publish the book online again, chapter by chapter and also consider creating some ebooks for those who prefer using readers. There’s a dark and light theme and it will work across all resolutions and platforms. I’m using jekyll/eleventy with GitHub pages and learn a few new things on the way.

Here’s the new table of contents:

  • About this handbook
    • About this version
    • About the author
  • What is Developer Advocacy / Evangelism?
    • Defining Developer Advocacy
    • Start with the right mindset
    • Find your role and play to your strengths
  • Work with your own company
    • Prepare for prejudice
    • Deal with company changes
    • Be there for internal developers
    • Work with PR and marketing
    • Be known as an outward channel
    • Train other advocates and developers
    • Share useful technology
    • Balance your personal and official channels
    • Remove the brand
  • Working with your competition
    • Work with the competition
    • Show respect to the competition
    • Acknowledge when the competition is better
    • Know about the competition
    • Build examples using and try out competitive products
  • Prepare for outreach
    • Get your facts right
    • Know the audience and their needs
    • Have expert backup
    • Choose the right medium
    • Plan for failure
  • Get speaking opportunities
    • Take part in podcasts
    • Take part in panels
    • Go to Grass Roots events
    • Go to Meetups
    • Write articles
    • Offer Brownbags
    • Ask questions at conferences
    • Be a presenter people want to invite – publish your presenter terms
  • Travel and conference participation
    • Getting your travel and accommodation sorted
    • Who pays what?
    • Be at the event
    • Give the event some social media love
    • Use the event to build a network
    • Keep track of your conference participation
    • Work with the conference buzz
    • Be a part of the conference you talk at
    • Release immediately
    • Write about conferences
  • Deliver a talk or workshop
    • Be yourself
    • Invite communication
    • Prepare takeaways
    • Plan time for and own the questions and answers
    • Be honest and real
    • Follow up communication
    • Delivering presentations tips: timekeeping and more
      • How will I fit all of this in X minutes?
      • Less is more
      • Your talk is only extremely important to you
      • Map out more information
      • Live coding?
      • Avoid questions
      • Things to cut
      • Talk fillers
      • Planning Your Talk Summary
    • Things not to say on stage – and what to do instead
      • “This is easy…”
      • “I’ll repeat quickly, for the few of you who don’t know…”
      • “Everybody can do that…”
      • “X solves this problem, so you don’t have to worry about it”
      • “As everybody knows…”
      • “This is just like we learned in school…”
      • “That’s why Y(your product) is much better than (competitor) X”
      • “This can be done in a few lines of code…”
      • “If you want to be professional, do X”
      • A quick check
  • Write great posts and articles
    • Simple is not stupid
    • Say what it is – don’t sugar-coat it
    • Size matters
    • Add media
    • Structure your content
    • Time-stamp your content
    • Cite to prove
    • Pre-emptive writing
    • Ending on an invitation to learn more
  • Write excellent code examples
    • Solve a problem with your example
    • Show a working example
    • Explain the necessary environment
    • Write working copy and paste code
    • Have the example as a download
    • Write clean and clever examples
    • Build code generators
    • Hosting code and demos
      • Version Control is your friend
      • Automated Hosting
      • Code showcases
      • Code Sandboxes
      • Live coding environments
  • Prepare great slide decks for presentations
    • Know your stuff
    • Start with the content – not the slides!
    • Start with a highly portable Format – Text
    • Quick Presentation creation tip: unpacking bullets
    • Pick a presentation tool that helps you present
    • Illustrate, don’t transcribe
    • Use and find images
    • About code examples
    • Sound and videos
    • Don’t bling it up
    • Keep it brief
    • Consider the audience
    • Corporate and conference templates
    • Don’t reuse without personalising
    • Share and enjoy
    • Additional presentation tips
      • Introduce yourself
      • Use humour
      • Build bridges to the real world
      • Pace yourself
      • Avoid “Hello World”
      • Be fresh
    • A checklist for more inclusive, accessible and understandable talks
      • Talk materials
      • Format
      • Content
      • Tracking
      • Insurances
      • Bonus round
  • Keep a record of your work
    • Record the audio of your talks
    • Shoot video
    • Link collections
    • keep a conference participation list
  • Know and use the (social) web
    • Find great web content
    • Redistribute web content
    • Be known on the web
    • Use powerful social web sites and products
    • Use the web for storage, distribution and cross-promotion
    • Hint, tease and preview
    • Track your impact
    • Build a network
    • Create or take part in a newsletter
    • Create or take part in a podcast
  • Working from your own computer
    • Get a decent setup
    • Screencasts and screenshots
    • Streaming
    • Taking part in live online chats
    • Attending live online events
    • Technical issues to prepare for
    • Design limitations to prepare for
    • Personal issues to prepare for
    • Recording your own talks
      • Check your setup and your surroundings
      • Record the different pieces of the talk separately
      • Remember that you need to share the screen with your slides
      • Use accessibility features to add extra video value
      • Record in the highest possible quality
      • Keep originals and make it easy to get your video
  • Final words

Chris Heilmann on his desk writing

Until then, I hope you have a great time and take some time off!