Accessible Clock? Almost…

analogue clock with black face Reading Time: 3 minutes

I adapted a coded clock from W3C Schools (home of the accessible clock canvas) on the Learning Too website’s Articles page. It’s a fun piece of bling drawn into an HTML5 canvas using JavaScript. Online Tutorials YouTube channel demonstrates a lighter-weight HTML, CSS, and JavaScript clock.

Both clocks lack inclusive design. Any assumption that our screen reader visitor can find the time from their system clock is ableist at best. And what of when we display clocks from around the World? The root question is on my mind everyday: why don’t we work harder to make our toys accessible?

The previously implemented analogue clock from my Articles page on Learningtoo.eu
System Clock Animation (requires JavaScript and an updated browser)

Here’s the YouTube demo. It looks cooler than my own clock simply for the sake of CSS. Behind the scenes it’s a group of div containers styled and animated using CSS and JavaScript. A PNG file is called as a clock face.

The video celebrates neomorphism. It’s an emergent visual design trend that gently bubbles flat design into a 3-dimensional and smooth texture. Sure, there’s a ripple of a clock rim and where are the clock hand shadows? All we would need do is repeat each hand, style it as a shadow beneath the ‘solid’ hand and position the (shadow) clock center a few pixels left and down? We can go so crazy – it’s just CSS, afterall.

What is the experience for screen reader users? There is none. We should try to improve on that.

Making the Clock Inclusive

The numerals in the original clock are a PNG image called using CSS. We don’t need it for everyone and it will help many people tell the time. I’ve called one hastily created in PowerPoint and uploaded to my parent domain. It is possible to create them with HTML and only adds an unnecessary complexity.

The Plan

The plan is simple:

  1. Make the analogue clock responsive
  2. Use the time data called by the JavaScript
  3. Input the time into a span in the paragraph above the clock:
    • for screen readers to parse
    • to offer two time display strategies for visual users to meet their ability or preferences
  4. Ensure the analogue clock is created from empty elements and will be ignored by screen readers

Giving it a Go

The New Clock

The time is unknown.

 
 
 

Outcomes

  1. Firstly, it scales responsively. Rather than sitting stagnant at 350 pixels by 350 pixels in case someone views it n a narrow viewport, it has relative widths and heights based on the viewport width (VW). That’s a limited effect within this column and quite awesome on its own page – it gets big! In any case, it’s now responsive to our viewport. Using EM units could add zoom in the browser, too.
  2. Next, we printed the current time to the screen. VoiceOver treats the containing span as a dimmed region. Moving VoiceOver forward reads the time and seemingly unreliably. Should it announce or be labelled or described with ARIA? Otherwise this does what I hoped – to read the time and ignore the HTML analogue clock.

Work In Progress

I’ve not found the full solution I am happy with yet. I really need help from a developer.

There’s not much in the first seven pages of searches relevant to the actual clock: lots on timers and inputs and nothing on clocks. I played with giving the setInterval a value (referenced from StackOverflow: Get code to run every minute) and removing the second counter. The second counter is a reassurance to visual users that the analogue clock is “live”. Screen reader users should enjoy the same experience.

I am working on it.

The New Clock Code

The HTML, CSS, and Javascript used to create the new clock

HTML

<p>The time is <span id="tellMeTime">unknown</span>.</p>
<div class="demoClock">
<div class="clock">
  <div class="hour">
    <div class="hr" id="hr"></div>
  </div>
 <div class="min">
  <div class="mn" id="mn"></div>
 </div>
 <div class="sec">
  <div class="sc" id="sc"></div>
 </div>
</div>
</div><!-- demoClock-->

CSS

.demoClock {
    display:flex;
    justify-content:center;
    align-items:center;
    background:#091921;
}
.clock {
    position:relative;
    width:350px;
    height:350px;
    display:flex;
    justify-content:center;
    align-items:center;
    background:url(clock.png);
    background-size:cover;
    border:4px solid #091921;
    border-radius:50%;
    box-shadow:
        0 -15px 15px rgba(255,255,255,0.05),
        inset 0 -15px 15px rgba(255,255,255,0.05),
        0 15px 15px rgba(0,0,0,0.03),
        inset 0 15px 15px rgba(0,0,0,0.3);
}
.clock:before {
    content:'';
    position:absolute;
    width:15px;
    height:15px;
    background:#ffffff;
    border-radius:50%;
    z-index:10000;
}
.clock .hour,
.clock .min,
.clock .sec {
    position:absolute;
}
    .clock .hour,
    .hr {
        width:160px;
        height:160px;
    }
    .clock .min,
    .mn {
        width:190px;
        height:190px;
    }
    .clock .sec,
    .sc {
        width:230px;
        height:230px;
    }
.hr, 
.mn, 
.sc {
    display:flex;
    justify-content:center;
    position:absolute;
    border-radius:50%;
}
    .hr:before {
    content:'';
    position:absolute;
    width:8px;
    height:80px;
    background:#ff105e;
    z-index:10;
    border-radius:6px 6px 0 0;
    }
    .mn:before {
    content:'';
    position:absolute;
    width:4px;
    height:90px;
    background:#ffffff;
    z-index:11;
    border-radius:6px 6px 0 0;
    }
    .sc:before {
    content:'';
    position:absolute;
    width:2px;
    height:150px;
    background:#ffffff;
    z-index:12;
    border-radius:6px 6px 0 0;
    }

JavaScript

The Clock

const deg = 6;
const hr = document.querySelector('#hr');
const mn = document.querySelector('#mn');
const sc = document.querySelector('#sc');

let day = new Date();
let hh = day.getHours() = 30;
let mm = day.getMinutes() = deg;
let mm = day.getSeconds() = deg;

setInterval(() => {
hr.style.transform = 'rotateZ(${(hh)+(mm/12)}deg)';
mn.style.transform = 'rotateZ(${mm}deg)';
sc.style.transform = 'rotateZ(${ss}deg)';
})

The Printed Time

setInterval(() => {
var timeNow = new Date();
var timeHours = String(timeNow.getHours()).padStart(2, '0');
var timeMins = String(timeNow.getMinutes()).padStart(2, '0');
var timeSecs = String(timeNow.getSeconds()).padStart(2, '0');
$('#tellMeTime').text(' ' + timeHours +':' + timeMins + ':' + timeSecs);
});

Reference this post

Godfrey, P. (Year, Month Day). Title. Retrieved , from,

Top

Leave a Reply