Showing posts with label css3. Show all posts
Showing posts with label css3. Show all posts

Saturday, May 26, 2018

Finding Your Way

One of the common challenges when writing interfaces is describing processes that have multiple steps in a way that is both understandable and accessible. Adding different functionality and different devices further complicates this. If we were Hänsel or Grethel, we would just leave a trail of pebbles or breadcrumbs.

Alas, we often find that even though we are not Hänsel or Grethel, navigation within a process is still often a problem and poorly written HTML or CSS can significantly contribute to the several common accessibility concerns and usability concerns surrounding the progress/breadcrumbs component as well. This post offers a pattern that is accessible and mobile friendly without being a burden.

Again, the HTML and CSS needed to provide a usable breadcrumbs component is relatively simple, but it can pose an even greater problem if it is not written correctly. It should also be noted that in addition to the pattern described here, it is very important that the page title and the primary heading should be modified to indicate the update progress.

When first building our progress bar or breadcrumbs, we must make the determination if our it represents unidirectional progress or if we might be able to restart the process. If the flow is unidirectional, you might consider using the progress element to demonstrate progress; however, be aware that the progress element is dependent on the OS in use, and the ability to modify the display is limited.

If we are providing the ability to move backward in the process - i.e., the process is not unidirectional - that means the breadcrumbs or progress bar has a navigational element, and it should be identified as such. The good news is that much of the code is unchanged. To demonstrate the difference in the code, both versions are provided below.

Image showing breadcrumbs with the current step highlighted, in both mobile and desktop.
Breadcrumbs Snapshot
The code below, is complete, with the exception that in the demonstration there is a style rule to center the content, and it produces the breadcrumbs show in the Breadcrumbs Snapshot.



HTML (without navigation)

<div class="breadcrumbs">   <ol >     <li>       <span data-step="#1" role="text">         <span class="description">Personal Information</span>       </span>     </li>     <li aria-current="step">       <span data-step="#2" role="text">         <span class="description">Financial Information</span>       </span>     </li>     <li>       <span data-step="#3" role="text">         <span class="description">Review Information</span>       </span>     </li>     <li>       <span data-step="#4" role="text">         <span class="description">Thank You</span>       </span>     </li>   </ol> </div>



HTML (with navigation)

<nav aria-label="Breadcrumb" class="breadcrumb">   <ol>     <li>       <a href="signup/1">       <span data-step="#1" role="text">         <span class="description">Personal Information</span>       </span>       </a>     </li>     <li aria-current="step">       <a href="signup/2">       <span data-step="#2" role="text">         <span class="description">Financial Information</span>       </span>       </a>     </li>     <li>       <a href="signup/3">       <span data-step="#3" role="text">         <span class="description">Review Information</span>       </span>       </a>     </li>     <li>       <a href="thankyou">       <span data-step="#4" role="text">         <span class="description">Thank You</span>       </span>       </a>     </li>   </ol> </nav>

A few items to note - one is the inclusion of the aria-current attribute, which lets users of assistive technology know which step is current, and another is the inclusion of the role attribute, which fixes a 'feature' in some assistive technologies that sees child elements as distinct from their wrapping elements, resulting in a different value for the accessible name than what would commonly be expected. Otherwise, the code should be self-explanatory.

Next, we add some CSS



CSS

.breadcrumbs {   display: inline-block;   width: auto; } .breadcrumbs ol {   list-style-type: none;   margin: 0 auto;   overflow: visible;   padding: 0; } .breadcrumbs ol li {   float: left;   background: darkgray;   border: 0.1em solid darkgray;   color: white;   padding: 0.5rem;   position: relative;   margin-right: 1rem; } .breadcrumbs ol li::after {   background: darkgray;   content: '';   display: inline-block;   height: 0.5rem;   left: 100%;   margin: 0;   padding: 0;   position: absolute;   top: 0.7rem;   /* width = margin-right + (border-width * 2) */   width: 1.2em;   z-index: -1; } .breadcrumbs ol li:last-of-type {   margin-right: 0; } .breadcrumbs ol li:last-of-type::after {   display: none; } .breadcrumbs ol li a {   background: inherit;   color: inherit;   text-decoration: none; } .breadcrumbs ol li[aria-current] {   background: green;   border-color: green;   color: white; } .breadcrumbs ol li[aria-current] ~ li {   background: lightgray;   color: black; } @media (max-width: 20rem) {   .breadcrumbs ol li {     border-radius: 100%;   }   .breadcrumbs ol li [data-step]::before {     content: attr(data-step);   }   .breadcrumbs ol li a .description {     clip: rect(0, 0, 0, 0);     clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);   position: absolute;   } }

Here again, we need to comment about the code. First, the .breadcrumbs ol li rule is for past steps. This allows us to use the aria-current attribute as the selector for current steps and siblings of aria-current after the aria-current item - .breadcrumbs ol li[aria-current] ~ li - are those steps not yet completed. Another issue to note is that we are using the float property on list items. We might have used the display property to modify where items display, but in many assistive technologies, modification of the display property modifies the accessibility tree, rendering all our effort to construct an accurate tree moot.


Admittedly, this is a simple example; however, it should suffice to demonstrate how a progress bar or breadcrumbs might be built.

Happy coding.

Tuesday, December 5, 2017

Print It!

Several years ago, Smashing Magazine did an article called 5 Powerful Tips and Tricks for Print Style Sheets, but we don't often remember print stylesheets today because, let's be honest, people don't generally print things anymore - at most, we save them to PDF on our device - but it is still an important part of the design of the interface.

Print stylesheets, however, can be pretty powerful, and there are a lot of times we still want a hardcopy of something we've worked on. In the financial services sector, we see this fairly often. People want a record of what they've signed up for - especially when it comes to paying interest. It doesn't really matter if the "hardcopy" is a PDF or a tree-killing version you can hold in your hands, we want it to look official.

There are a few things you'll want to keep in mind when printing, but generally, read the Smashing Magazine article I've linked above. One issue the Smashing Magazine article doesn't go into detail about is font size. Don't mess about with the font size. There are loads of posts about accessibility and font size and how to use rem or em rather than px on a web page - the same holds true for printed versions. You don't want someone getting the small print version when what they see on the screen is large print.

One thing that deserves a special callout - the Smashing Magazine article talks about expanding links and this is very important. In printed versions the user will not (generally) have the ability to hover over or follow a link, so make sure the appropriate links are followed by the URL in plain text. I'd suggest making certain the following is in your print stylesheet.



CSS

a:not([href^=javascript]):after {   content: " <" attr(href) "> "; } a[href="#"]:after {   content: "" !important; }


I'm going to go a little further here, because if you wish to exclude other links, let's say anything linked to "foo.com", for example, simply add those to the first rule, and use the in-string regular expression operator, like so...


CSS

a:not([href*=foo\.com]):not([href^=javascript]):after {   content: " <" attr(href) "> "; } a[href="#"]:after {   content: "" !imporant; }


...and you've included the link, enclosed in < and >, in your printed versions.

You'll notice, that on line one there are two differences in the attribute selector. First, I'm using a different regular expression selector, *= and second, I have a \ before the "." in "foo.com".

The selector *= matches a partial value in an attribute (you can learn more about regular expressions in attribute selectors at https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors), so take care that you have the most complete partial possible - in my example, links to barfoo.com would also be excluded.

Additionally, the . is a special character in CSS syntax (as are ":" and "/"), which means it will need to be escaped in order to be seen as part of the value, just as "http://www.foo.com" would need to be escaped as "http\:\/\/www\.foo\.com".

That's all there is to it - powerful selectors and the function that returns an attribute can make your printed (and saved-to-PDF) documents better for your users.

Happy coding.

Friday, January 20, 2017

Gather Ye Rosebuds: thoughts regarding collecting date values

One very common data types that we collect from users is a date value, whether it be a birthday or other anniversary or even something like a booking date for an event. Unfortunately, most of the date collection methods I've seen in the past two decades are sub par and the failure is even more pronounced when we consider the experience for those using assistive technology.

We've made some progress - we now, in HTML5, have a date type INPUT tag - but even there the experience is lacking. If we add in other considerations - like internationalization - we slide even further down this slippery slope, opting to do things like collect the date parts, i.e., month, day, and year, individually to make sure we have a valid date that's gathered in a manner that is somewhat familiar to the user.

Of course we have tools like datepicker, but unfortunately those are typically only partial solutions. Sure, they improve the interface for a number of users, but most still fall short, especially for those using screen readers...and that situation becomes even worse when they insert a calendar widget into a popup and focus is not managed well.

What's the solution?

Ideally, a tool that would automatically generate a visual calendar in the most common layout - a table with seven columns with each week in a row - and some common controls - like the ability to change the month and/or year using a next/previous button or a drop down list. The control should be in the flow of the document and it should include, at the very least, ARIA-* and role attributes so the experience doesn't suck if you're using a screen reader. Oh, and you should be able to navigate it easily using the keyboard, a mouse, or a touch-enabled device.

I don't really think that's asking too much. All it's really asking is that we, as UI engineers, consider how the experiences we are building are impacting people who are not like us. Maybe that's more along the lines of "everything and a kite" than "not too much", but I like to think we can do better than just OK. I'd like to think that when we talk about the MVP we're not really thinking about the MVE (Minimum Viable Effort - look for that in an upcoming post).

Now for a little good news. I've begun building such an interface. Since everyone seems to be hot after Angular these days, that's what I've used and I've built a prototype with a calendar directive. Granted, it's not 100% complete - there's still a little work to do to improve the accessibility and internationalization - but it's about 99 percent there. (You can see the prototype at http://prototypes.cathmhaol.com/ng-calendar/.)

The directive is not yet on my github, but it will be as soon as I've rounded a few of the rough corners, but you can easily download the source and the CSS (which includes a special trick that forces the table cells into squares) from the prototype if you're dying to get started building out a better date collector.

As always, happy coding.

20 February, 2017
The interface is complete and is available on GitHub at https://github.com/hrobertking/angular/tree/master/ng-calendar. A brief demonstration is below.

Friday, November 4, 2016

You've Got Mail: Easy, accessible notifications

Today it's just a quick post to talk about how to do those notifications we've come to know – and since they are relatively simple, this will be short and to the point. An image is provided to show a basic example of what I'm describing.

First, let's start with the markup.

Since you'll likely have a list of possible notifications – for example, alerts or messages – put them in an unordered list. Each list item will contain a count of items and a type of items as well as a link to the item viewer. This will give you markup something like the example below. Note that this markup is fully accessible as is; however, the accessibility may be improved by adding a label to the unordered list identifying it as a list of notifications.



HTML

<ul class="notifications">   <li role="status">     <a href="/alerts.htm">       <span class="count">4</span>       <span class="type">Alerts</span>     </a>   </li>   <li role="status">     <a href="/messages.htm">       <span class="count">100</span>       <span class="type">Messages</span>     </a>   </li> </ul>


If the notifications are a live region – if they're automatically updated while the page is displayed in the browser – be sure to add the role attribute and set it to status so that changes are announced when the content is updated. To show how that would work, the role attribute is included in the example. It is important to note that the markup be readable as is, regardless of where the message parts, i.e., the count and type, are displayed.

Next, you'll add the style rules.



CSS

ul.notifications { nbsp;nbsp;margin:0;   padding:0;   text-align:right;   font-family:Verdana; } ul.notifications > li {   display:inline-block;   overflow:auto;   margin-right:1em; } ul.notifications > li:last-of-type {   margin-right:0; } ul.notifications > li > a > span.count, ul.notifications > li > a > span.type {   display:block;   position:relative; } ul.notifications > li > a > span.count {   background-color:rgb(255, 255, 255);   border:1px solid rgb(0, 0, 0);   border-radius:2em;   float:right;   font-size:0.5em;   text-align:center;   line-height:2em;   padding:0.2em;   width:2em;   z-index:1; } ul.notifications > li > a > span.type {   float:left;   line-height:3em;   z-index:0; }

Here, you'll want to pay special attention to setting the overflow to auto on the list item (this will make the list item contain the floating items), and setting the border-radius to the same value as the line-height on the span with class count – 2em in the example. Setting the height, width, and border-radius all to the same value will give the circle effect. Using a value of 2em for height and width with a font-size of 0.5em will allow you to easily display 3 digits within the circle. Also, be sure to set the z-index on the count to 1 in order to force it to display over the type. It is especially important to set the z-index when the background is set, otherwise the overlap will likely not work as you intend.

You'll notice that in our example, the count span is floating to the right and the type span is floating to the left. This floating pattern makes the count float over the lowercase portion of the type, meaning less content is hidden when there is overlap. You may just as easily float the count span left and leave all remaining code the same in order to have the number displayed on the left side of the type text.

Once you've set the HTML and CSS, you're ready to add any JavaScript you wish, for example, to make the notification viewer display as a modal window or automatically refresh the number of items in the count element.

That's it - you have all the code you'll need to make easy, accessible notifications, so...

Happy coding.

Wednesday, July 6, 2016

Tooltips sans Bootstrap

If you're using Bootstrap to do tooltips, you're doing it wrong, and your site's performance probably shows you're doing it wrong.

Here's an example I've seen recently

HTML
<a href="#" data-toggle="tooltip" title="Get you some of that">   <h2>GYSOT</h2> </a>

Here are a few problems with this approach:

  1. if you're doing it this way you're not only using the Bootstrap CSS file (which to be honest is a little bloated) but you're also using Bootstrap JS
  2. your code is not semantic
  3. your code has a few extra accessibility issues

It would be more semantic if the markup was something like…
HTML
<h2 data-toggle="tooltip" title="Get you some of that">GYSOT</h2>

...but that doesn't really solve any performance issues your users are experiencing because of all the extra goodies Bootstrap includes that you're not using – and it doesn't solve the accessibility issues. That's why it would be nicer if we wrote the markup as…

HTML
<h2 aria-label="Get you some of that" class="has-tooltip">GYSOT</h2>

Here's the thing. Not only is this less markup, but here's all the CSS you'll need to put in a tooltip.

CSS
.has-tooltip {   display:inline;   position:relative; } .has-tooltip:focus:after, .has-tooltip:hover:after {   background:rgba(200, 200, 200, .9);   border:0.1em solid rgb(128, 128, 128);   border-radius:0.3em;   bottom:1.3em;   color:rgb(0, 0, 0);   content:attr(aria-label);   left:0;   padding:0.1em;   position:absolute;   z-index:1; } .has-tooltip:focus:before, .has-tooltip:hover:before {   border-color:rgb(128, 128, 128) transparent;   border-left:0.3em solid transparent;   border-right:0.3em solid transparent;   border-top:0.3em solid rgb(128, 128, 128);   bottom:1em;   content:"";   left:50%;   position:absolute;   z-index:2; }


It really is that simple to display a tooltip directly above some text and to make the content of the tooltip directly accessible.

A couple little notes - if you want to display the tooltip on the bottom of the you'll have to adjust the bottom values for both the before and after pseudoclass rules and if you want to display the tooltip with a different font or font-size you'll have to adjust those on the before and after pseudoclasses as well. All the detailed customization aside, this should get to started down the road to ditching Bootstrap.

Happy coding.

Monday, June 6, 2016

Scrolling, Scrolling

When you're short on real estate on your web page, one of the easiest things to do is shorten the height of an element and make it scrollable. This works especially well with a table, but if you're not careful, the header of the table will scroll along with all the content, making the column headers invisible and rendering the table more difficult to use. Fortunately, fixing this problem is relatively easy - as you'll see below.

First, you really should start with good, clean, semantic markup. That means a THEAD tag and a TBODY tag. So we'll start with something like the following...

HTML
<table class="scrollable">   <caption>10 of the world's busiest airports</caption>   <thead class="thead">     <tr>       <th>Country</th><th>City</th><th>Activity</th><th>Name</th><th>Latitude</th><th>Longitude</th>     </tr>   </thead>   <tbody>     <tr><td>US</td><td>ATL</td><td>68343</td><td>Hartsfield Jackson Atlanta International</td><td>33.636719</td><td>-84.428067</td></tr>     <tr><td>US</td><td>ORD</td><td>59692</td><td>Chicago O'Hare International</td><td>41.978603</td><td>-87.904842</td></tr>     <tr><td>US</td><td>DFW</td><td>56496</td><td>Dallas Fort Worth International</td><td>32.896828</td><td>-97.037997</td></tr>     <tr><td>US</td><td>LAX</td><td>51396</td><td>Los Angeles International</td><td>33.942536</td><td>-118.408075</td></tr>     <tr><td>CN</td><td>PEK</td><td>48226</td><td>Capital International</td><td>40.080111</td><td>116.584556</td></tr>     <tr><td>US</td><td>CLT</td><td>44583</td><td>Charlotte Douglas International</td><td>35.214</td><td>-80.943139</td></tr>     <tr><td>US</td><td>DEN</td><td>44438</td><td>Denver International</td><td>39.861656</td><td>-104.673178</td></tr>     <tr><td>US</td><td>LAS</td><td>41164</td><td>McCarran International</td><td>36.080056</td><td>-115.15225</td></tr>     <tr><td>US</td><td>IAH</td><td>39808</td><td>George Bush Intercontinental</td><td>29.984433</td><td>-95.341442</td></tr>     <tr><td>GB</td><td>LHR</td><td>37680</td><td>London Heathrow</td><td>51.4775</td><td>-0.461389</td></tr>   </tbody> </table>


Next, we need to adjust the CSS to override the default styles.

First, make sure that you have at least some specificity, otherwise all your tables, even those that take up very little vertical space will be affected. You'll notice from line 1 of our HTML that we're doing this by adding scrollable as a class on the table.

Second, we're adjusting both the TBODY and the TR tags to override the default. We're going to add a rule for overflow (on the y-axis) on the TBODY and for the height. A note about the height - the default line-height for a table row is 1.5 em, so if you don't adjust the line-height, using a multiple of 1.5 will give you a full line at the bottom - assuming you don't have borders around the TR or TD. In the example, I'm using a 6em height, which shows 4 full lines.

One might think that setting the height and overflow-y on the TBODY is enough, but alas it is not. The display mode is still table, which overrides the height specification. To correct this, I'll change the display to block. Unfortunately, that has the sad side-effect of rendering the cells within the table using an auto width. I'll correct this - in part by setting the display on the TR to table - and in part by setting the width on each of the columns. This gives us the CSS below.

CSS
table.scrollable > tbody {   display:block;   height:6em;   overflow-y:scroll; } table.scrollable > thead, table.scrollable > tbody tr {   display:table; } table.scrollable th:nth-child(1), table.scrollable td:nth-child(1) {   width:5.5em; } table.scrollable th:nth-child(2), table.scrollable td:nth-child(2) {   width:4em; } table.scrollable th:nth-child(3), table.scrollable td:nth-child(3) {   width:5.5em; } table.scrollable th:nth-child(4), table.scrollable td:nth-child(4) {   width:17em; } table.scrollable th:nth-child(5), table.scrollable td:nth-child(5) {   width:5.5em; } table.scrollable th:nth-child(6), table.scrollable td:nth-child(6) {   width:6.5em; }

If you would rather have evenly-spaced columns, you can set the width on the TR within the TBODY to 100% and change the table-layout to fixed, e.g., change line 8 in the CSS to display:table; table-layout:fixed; width:100%; and remove lines setting width on all columns.

That's it. Your table is now scrollable with a stationary header.
10 of the world's busiest airports
CountryCityActivityNameLatitudeLongitude
USATL68343Hartsfield Jackson Atlanta International33.636719-84.428067
USORD59692Chicago O'Hare International41.978603-87.904842
USDFW56496Dallas Fort Worth International32.896828-97.037997
USLAX51396Los Angeles International33.942536-118.408075
CNPEK48226Capital International40.080111116.584556
USCLT44583Charlotte Douglas International35.214-80.943139
USDEN44438Denver International39.861656-104.673178
USLAS41164McCarran International36.080056-115.15225
USIAH39808George Bush Intercontinental29.984433-95.341442
GBLHR37680London Heathrow51.4775-0.461389


Happy coding.

Monday, April 4, 2016

An Even Better Credit Card

One of my most popular entries on this blog is the inline credit card entry form highlighted in A Better Credit Card.

While that overall design is efficient, it does not necessarily reduce the cognitive load of a page, and cognitive load is often a significant factor in conversion and general usability. After writing about using CSS transform to flip an image, I decided to revisit the card entry form to consider how it might be modified to reduce cognitive load. In the end, I decided to use a skeuomorphic pattern and build a prototype for card entry (which you can see in my prototype collection).

One word of warning before we begin: elements are positioned, shown, and hidden using CSS, but there is no way to modify the class attribute without using JavaScript. I am advising, therefore, that even though the markup can be used as-is, the CSS be initially applied using JavaScript. This step is not done in the prototype.

Here's how the prototype was built...

First, as I always do, I started with the markup. Since I'm using a skeuomorphic design pattern, my card entry form uses the card type, the account number, the customer's name, the CSC (or, as we say in the US, the CVV), and the expiration date and skips other inputs, like a starting date (does anyone even have a Switch or Solo card anymore?). Although it's not purely semantic, I did add a visual element for the mag stripe on the back of the card.

HTML
<form id="card_entry">   <div class="card" id="card">     <p class="magstripe" aria-hidden="true"> </p>     <fieldset class="card-type" id="card-type">       <legend>Card Type</legend>       <span class="card-icon">         <input id="amex" name="card_type" type="radio" value="amex">         <label class="card-type-label" for="amex">American Express</label>       </span>       <span class="card-icon">         <input id="visa" name="card_type" type="radio" value="visa">         <label class="card-type-label" for="visa">Visa</label>       </span>       <span class="card-icon">         <input id="mastercard" name="card_type" type="radio" value="mastercard">         <label class="card-type-label" for="mastercard">Mastercard</label>       </span>     </fieldset>     <p class="acct">       <label for="acct">Account number</label>       <input id="acct" name="acct" type="text" value="4123 4567 8901 2349">     </p>     <p class="name">       <label for="fn">Name on Card</label>       <input id="fn" name="fn" type="text" value="jane doe">     </p>     <fieldset class="expiry">       <legend>Good Thru</legend>       <p class="date">         <label for="expiry_mo">Expiration Month</label>         <input class="mo" id="expiry_mo" name="expiry_mo" type="text" value="12">         <span class="separator" aria-hidden="true">/</span>         <label for="expiry_yr">Expiration Year</label>         <input class="yr" id="expiry_yr" name="expiry_yr" type="text" value="25">       </p>     </fieldset>     <p class="security-line">       <span class="signature" aria-hidden="true">Your signature</span>       <label for="cvv">CVV</label>       <input class="cvv" id="cvv" name="cvv" type="text" value="123">     </p>   </div>   <button id="cardflip" aria-hidden="true" style="margin:1em;" type="button">?</button> </form>


Note
Although you will often need to collect an address along with card information, it will be to your advantage to create an address collection form component, because the format for each country is specific and creating a component - even a component for each country - will mean you won't have to repeat that work. Credit and debit cards, on the other hand, generally follow a single form regardless of country.

As you'll notice, the markup follows accessibility guidelines. Each INPUT has an associated label, there is a LEGEND tag for each FIELDSET element, and elements that are purely visual are hidden using aria-hidden. This is very important and is one of the ways we make sure the markup is semantic. To ensure the accessiblity features don't interrupt the visual representation, breaking our skeuomorphic pattern, I'm using absolute positioning with a clipped rectangle (which has proven to be the approach most recognized by assistive technology) to hide elements not visibly present on a physical card.

The meat in this dish is the CSS (rather than give a complete code listing here, I'm going to link to the stylesheet). The stylesheet not only positions the account number, name, CSC, and expiration date, it will either invert the card and display the CSC entry field (for any card not an American Express) or display the CSC entry field on the front of the card (for an American Express card).

CSS
.card {   background-size:cover;   background:rgba(100, 160, 200, 1) url("blank_card.jpg");   border-radius:10px;   border:1px solid rgba(170, 170, 170, 1);   font-family:monospace;   font-size:12px;   font-weight:800;   height:14em;   line-height:12px;   margin:0;   overflow:hidden;   padding:1em 0;   transition:transform 1s;   width:25.5em; } .card.invert {   background:rgba(100, 160, 200, 1);   -ms-transform:rotateX(0deg) rotateY(180deg);   -webkit-transform:rotateX(0deg) rotateY(180deg);   transform:rotateX(0deg) rotateY(180deg); }


By placing the transform rule on the card (CSS lines 17-22), the account number, name, and expiration date are all rotated as a single unit, leaving the matter of shifting the text-shadow and color to make the text appear inset rather than outset (since the name and account number are embossed on the card). All that remains after changing the text effect is hiding or revealing elements that are printed (not embossed), only appear on the front or back of the card - the expiration date label and magstripe, for example. Creating a 1 second transition effect for the transform (CSS line 14) animates the flip, reducing (or eliminating) the cognitive load associated with the interface change.

Note
To address the slight differences in Internet Explorer, there is an IE 9 stylesheet included in the prototype using a conditional comment and CSS rules (at the end of the card.css stylesheet) that look for IE 10 or IE 11 in the data-useragent attribute of the HTML. You can add the data-useragent to the HTML element by adding the following to your document head: <script>document.documentElement.setAttribute('data-useragent', navigator.userAgent);</script>


The prototype also includes some vanilla JavaScript that will change the class attribute of the card type input when the card type RADIO input is checked (using the onchange event) and will change the class attribute of the DIV card element to flip the card. Generally, if the user shifts focus to the CSC, we check to verify that we should invert the card (that the card is not an American Express). All other inputs are on the 'front' of the card so if focus moves to any other input, we remove the 'invert' class and show the front. The JavaScript provided as part of the prototype should not be used as anything other than a general guideline of how the interface should behave - it does not follow best practices because it is intended to be thrown away and is in its most basic, generally understandable form. Note: the JavaScript for this prototype will likely be modified in the future to enhance the prototype.

Note
The prototype also has a button that will flip the card so it's a little more mobile-friendly, specifically for devices that don't have a 'next field' button when entering data into forms. This button (HTML line 43) is separate from the card DIV but is placed close to the card so its meaning is a little clearer.


That's pretty much all there is to it - a skeuomorphic credit card entry form that will reduce cognitive load. There will be users who are more comfortable using it than the quicker inline form...but remember, you need to A/B test any changes to your user interface to figure out which is better for your users.

Happy coding.

Monday, February 22, 2016

A Modern Menu

I've been exploring a little, stretching my coding muscles again to see just how easy it would be to write an accessible navigation menu that slides out from the left on mobile but lies horizontally on a wide(r) screen. Now, let me begin by saying that writing one is easy...but writing a progressive, fully semantic version is not necessarily so. This post, however, will explain just that - how to write a progressively enhanced, fully semantic version that is accessible.

Rather than bore everyone with tedious code listings (yes, I'll have a few), I'm going to link to the proof-of-concept that will also have fully commented code, and here I'll give a general overview as well as a few things you'll want to notice along the way.

If this is your first foray into accessible coding, do yourself a favor and get the WAVE Evaluation Tool extension for Google Chrome, and if you're not already using the Mobile/Responsive Web Design Tester extension, get that as well.

As always, we first start with the markup and do the things we would normally do - add the lang attribute to the HTML tag, add a descriptive TITLE to the HEAD, and add a descriptive H1 to the BODY. Here's where I start my navigational menu code...inside the H1. In addition to using the H1 as a banner, I'm adding a 'button' that will toggle the navigation menu (note that this is only for mobile devices). Since this is only a visual interface for the menu, I'm not adding anything to it - no ARIA role labels. The 'button' span is empty, so without ARIA labels or role, accessibility technology will ignore it (as it should). After the H1, I'll add the actual menu...but more on that in a couple of paragraphs.

The user interface for mobile users, when the navigation menu is closed, will show a button that will display a hamburger symbol and when it's open it will display the x typically used on close buttons.

Note that I'm not actually using a BUTTON tag but a SPAN tag that acts like a button...and the primary reason for this is because the icon displayed inside the button is controlled using CSS and that's really impossible to do when you use a BUTTON tag. By attaching an event listener to the click event on the button SPAN, I add (or remove) opened to (or from) the H1 tag. The opened H1 and an adjacent sibling selector for the menu will control whether the menu is seen or not. If you want to use a different device to toggle the menu, feel free - and simply change the CSS so that the 'opened' class is attached to the menu. Since the content is not in the markup, I don't need any ARIA attributes like aria-hidden even though it's a control for the visual interface...and because the button in the H1 is only used on mobile, I wrap the styling in a media query using a mobile breakpoint.


HTML
<body>   <h1>     <span class="banner">Responsive Navigation Menu</span>     <span class="mobile-only button open close"></span>   </h1>   <div class="menu-overlay">


CSS
@media screen and (max-width:480px) {   h1 > .banner {     float:left;     height:1.65em;     line-height:1.65em;     width:80%;   }   h1 > .button {     border-radius:0.1em;     border:0.01em solid #ccc;     cursor:pointer;     display:inline-block;     font-size:1.25em;     font-weight:800;     height:1.1em;     padding:0.1em;     position:static;     width:1.1em;   }   h1 > .button.open.close::after {     content:"\2261";     cursor:pointer;     display:inline-block;     font-size:1.5em;     line-height:0.75em;     text-align:center;     width:0.75em;   }   h1.opened > .button.open.close::after {     content:"\00D7";   }

Now that we have the H1 set, I'm going to add the navigation menu to the page. I'm choosing to add the navigation menu before the content because (1) it's easier to style that way and (2) when the links are at the top it's easier for someone to jump to another location before all the other content is read - and they don't have to take extra steps, like using their AT to step through a bunch of landmarks.

HTML
  </h1>   <div class="menu-overlay">     <ul id="main-menu" role="navigation">       <li class="item">         <a href="?menu-item-1">Menu Item 1</a>         <span class="indicator"></span>       </li>       <li>         <a href="?menu-item-2">           Menu Item 2         </a>         <ul class="submenu">           <li class="item">             <a href="?menu-item-2.menu-item-A">               Menu Item A             </a>           </li>           <li class="item">             </a href="?menu-item-2.menu-item-B">               Menu Item B             </a>           </li>         </ul>         <span class="indicator"></span>       </li>     </ul>   </div>

There are a few things of note in the code. First, I've added a ARIA role (navigation) to the list. Rather than go into detail here about what a navigation role means, I'll instead point you to the W3 page about ARIA roles. Second, this example uses a sub-menu, which will become important when we talk about the CSS and the JavaScript. Additionally, I've identified LI items that contain menu items as items, which enables me to add LI tags that are used as separators. Each clickable item is wrapped in an anchor (A) tag, which allows me to leave sub-menu headers in tags that aren't automatically identified as clickable, e.g., SPAN. Finally, there is a SPAN tag with the class indicator regardless of whether or not there is a sub-menu. This enables a sub-menu visual indicator, which is not needed by accessibility technology, which will read the submenu because it's hidden using clip rather than a technique that would render the sub-menu invisible to AT.

CSS
ul[role="navigation"] > .item > .submenu {   background-color:#fff;   border-top:none;   border:1px solid #ccc;   box-sizing:border-box;   clip:rect(0, 0, 0, 0);   color:#333;   left:0;   list-style-type:none;   margin:0 -1px;   padding:0.5em;   position:absolute;   right:0;   transition:clip 1s;   z-index:3; }


There are a few things of note about the CSS. First, the style rules for the sub-menu will drop the sub-menu below the primary menu and make it appear as wide as the primary menu. Although this approach is not ideal, we're going to fix it using JavaScript - which will hit most users and those who don't have JavaScript running (or those who have a page with borked JavaScript) will still have access to the navigation menu. If you're coding for a mobile device and are using a toggle button, you might want to consider how users will get to the menu if their JavaScript is borked - you might even consider using a focus or hover pseudoclass.

Second, the initial value of the margin-left and margin-right is the border-width on the primary menu (ul[role="navigation"]) multiplied by -1. This extends the left and right border to the full width of the primary menu.

Third, by setting the position to absolute, we can change the left and right values and the menu will become more like a drop-down menu (remember that I said we'd fix the width of the menu with JavaScript just two paragraphs ago - well here it is, the initMenu function does it).

JavaScript
function initMenu(menu) {   var contained,       count,       index,       items,       mnu_item;   items = menu.getElementsByTagName('li');   count = items.length - 1;   while (count > -1) {     mnu_item = items.item(count);     contained = mnu_item.childNodes;     index = contained.length - 1;     while (index > -1) {       if ((/\bsubmenu\b/).test(contained.item(index).className)) {         contained.item(index).style.left = mnu_item.offsetLeft + 'px';         contained.item(index).style.margin = '0';         contained.item(index).style.right = 'auto';         break;       }       index -= 1;     }     count -= 1;   } }

Now, simply add a call to your JavaScript function to initialize the menu - something like initMenu(document.getElementById('main-menu')); - and you're done. The initMenu function will set the left position of the sub-menu UL to the left position of its LI container, will set the right value to auto (which shortens the width) and adjusts the margin so that everything lines up neatly.

So that's it. One last note - although I generally use a 'mobile first' approach (making the style sheet for mobile and then writing a media query for everything else) I didn't do it that way this time because the styles are different enough that they're difficult to re-use. In the proof of concept I've linked both stylesheets, but in your production code you might want to pursue an adaptive approach so only the mobile stylesheet is downloaded for mobile devices to minimize the payload - on the other hand, the stylesheets are pretty light as they are so it might not matter. Oh...and this is the proof of concept.

Happy coding.



Monday, February 8, 2016

A Question of Semantics

Aztec pyramidOver the past (nearly) 20 years, one of the webhead topics for which I have been an advocate is the creation of semantic code. In the beginning, it was "semantic markup" because markup was really all we had. A little while later we added stylesheets and several of us also began thinking in terms of semantic styles. Now we're seeing other features, such as animation, carry meaning and are beginning to think of them in "semantic" terms as well1. Each of these has been layered upon the other - a figurative Aztec pyramid. semantic and what does it mean to write semantically and why worry about whether or not our markup, or CSS, or any other level of code is semantic?

First, let's address what we mean by writing "semantic code".

Let's begin by saying that not all code is semantic. We spend significant time considering the content of a web site, a page, or an application and how it carries meaning, but the code that wraps the content can either carrying meaning or not. When I wrap content in a DIV or P tag, I know something more about the content than content that is simply terminated with a line break (BR tag). If I use HTML5 and wrap content in an ASIDE tag or ARTICLE tag, I know even more about the content than if I had wrapped them in a DIV or P tag.

As another example, if I wrap a number in a SUP tag the only thing I know about that number is how it should be displayed; however, if I wrap a number in a SPAN tag with a semantic class attribute - footnote, for example - I now know something more about that number. Similarly, when I add WAI-ARIA2 attributes, such as aria-describedby even aria-hidden I am describing the content even more fully3 just as surely if I use an EM or STRONG tag instead of an I or B tag.

To put it simply, semantic code includes not only content, but meta-communication about that content.

So, why worry about whether or not our markup, or CSS, or any other code is semantic? The simple answer is that the meta-communication in code is as important, and in similar ways, as tone and body language are in verbal communication. The importance of meta-communicating code is easily seen when assistive technologies, such as screen readers like JAWS or VoiceOver, are used. Simply consider the difference between a I (italics) tag and an EM (emphasis) tag or a B (bold) tag and a STRONG (strong emphasis) tag. One category is visually oriented, but the other is both visually and verbally oriented, leading to a not only richer, but more precise, experience...one with less cognitive load...and the lower the cognitive load, the better the user experience (which anyone who is "customer-focused" wants).

At this point you might be thinking "I see the importance of semantic markup and using ARIA semantics, but why bother with the rest". Consider this - what do you think your experience would be like if face-to-face communication were missing an element of meta-communication. Would you gather as much meaning? Would it be as complete? As a society, we generally don't think so, which is why we have all sorts of assistive technology intended to help us compensate for missing elements - each element is significant. This significance should be carried over into the coding world. I would posit that we ought to go so far as to say that when any element of the code does not qualify as semantic that the code as a whole is not semantic.

At this point we have only discussed general benefits of semantic code in relation to humans. I haven't even touched on the benefits of semantic code in relation to machines. By using semantic CSS, for example, browser plugins are able to interface more fully with other applications - like calendars - especially when the CSS is a microformat. This opens the door to creation of a number of symbiotic relationships between your code and existing applications, especially in mobile channels where we have merely scratched the surface.

Beyond what we typically think of as code, however, we must also make sure other features - like animation - are semantic (seriously, if you haven't read Motion with Meaning: Semantic Animation in Interface Design yet, go do it) or, at the very least, don't break our semantic model, just as we ought make certain those features in the user interface do not increase cognitive load. One of the methods people who design user interfaces have used for decades that helps maintain a semantic approach and also tends to reduce cognitive load is skeuomorphism4. One of the most common historic examples of this method is making a data input form mimic the paper version; however, there are numerous other examples - folder and file images for directories on a computer or an image of a envelope for mail or email are just two examples.

In a previous post I wrote about a different (credit/debit) card input form I had developed5. Although that post discussed, in more general terms, creating a form that validates a credit/debit card including determining the brand, it links to an input form that uses a minimalist style - and there are reasons to use a minimalist, semantic approach at times - and contains the JavaScript to perform the validation. One of the deficiencies in that prototype, however, is the lack of semantic animation (in the minimizing of the account number input). That deficiency is addressed in another prototype where I take a skeuomorphic approach and create a card input form that looks and behaves much like its real-world counterpart. Feel free to take a look at both prototypes and see which is a more complete, user-friendly experience. I'm confident you'll find the more complete the semantic approach, the better the experience. (Of course, a combination of the two - the technical validation of version 1 and the skeuomorphic design of version 2 - is probably closer to ideal.)

All the issues I've brought to the fore so far are focused on the customer (user) experience, as they should be. However, there are other sides to the use of a semantic approach - SEO advantages and your (hopefully) friendly interface engineer, for example. Although the SEO benefits of the use of semantic markup and styles are becoming less dramatic than they were in the past, they are still present, and that will likely not change. A document a machine can read and understand will always fare better than one that is less understandable. As for interface engineers - semantic code makes understanding what is likely to be a complex solution a little easier. Reducing the cognitive load for an interface engineer generally means more productivity and less frustration. More productivity and less frustration will generally result in better code, so getting into the practice of writing semantic code can become a self-reinforcing loop and make the world a better place. Best of all, it means more happy coding.

Reference Notes (please note that links open in a new window).
  1. Al Hazwani, Amin and Bernard, Tobias. Motion with Meaning: Semantic Animation in Interface Design. A List Apart. 19 January 2016. http://alistapart.com/article/motion-with-meaning-semantic-animation-in-interface-design (accessed 31 January 2016)
  2. The WAI-ARIA specification divides the accessibility semantics into roles, states, and properties. You can see that specification at https://www.w3.org/TR/wai-aria/usage.
  3. The WAI-ARIA semantics are very powerful, and getting their usage just right can be difficult, so if you're new to the whole "Accessible Rich Internet Applications" space, start with the W3C's ARIA Primer.
  4. Skeuomorphism is the practice of making virtual items - such as data input forms - resemble their real-world counterpart. (https://www.techopedia.com/definition/28955/skeuomorphism)
  5. King, Robert, 'A Better Credit Card', Getting Paid to Think [weblog]. 28 December 2012, http://gettingpaidtothink.blogspot.com/2013/02/a-better-credit-card.html.

Friday, January 15, 2016

A Simple CSS Transform

One of the more interesting things browsers are supporting now are 3D transformations - and using them you'll hit about 90% of your users. Are they incredibly useful...as useful as say calc or regex-style selectors? No. But I'm all about progressive enhancement, and reducing cognitive load and this can go a long way to that.
Since most of my experience is in working with the financial industry, I'm going to give you a real-world example of how you might use this nifty little feature, albeit simplified, while also explaining just how it can be done.

I'm going to construct a page that has a credit card entry form and also an image to explain show where to get the numbers. For this example, I'm only going to use two rather simplified images (shown here); however, the image of the card back will be flipped horizontally before being saved as a JPEG.

In a real-world use, I would likely use several images of the front, each highlighting a data point, e.g. account number, expiration date, and name, and tie each of those images to the focus pseudoclass for the appropriate field, but as this is only an example, I'm trying to simplify it here. Of course that also means that code listings are going to be somewhat incomplete.




HTML

<span class="help">?</span> ... <div class="card"></div>




CSS

.help {   background:#efefef;   border:1px solid #ddd;   border-radius:0.7em;   cursor:pointer;   display:inline-block;   font-weight:bold;   height:1.2em;   margin-right:2em;   text-align:center;   width:1.2em; } .help:hover + .card {   background-image:url("creditcardback.jpg");   -webkit-transform:rotateX(0deg) rotateY(180deg);   transform:rotateX(0deg) rotateY(180deg); } .card {   background:#fff url("creditcardfront.jpg") no-repeat center;   border-radius:5px;   border:1px solid #000;   clear:both;   float:none;   height:120px;   width:180px;   -webkit-transform:rotateX(0deg) rotateY(0deg);   transform:rotateX(0deg) rotateY(0deg);   -webkit-transform-style:preserve-3d;   transform-style:preserve-3d;   transition:transform 1s; }

Using the transform to rotate on the Y-axis (lines 15/16 and 27/28 in the CSS listing) flips the image on the horizontal axis in a one second animation (line 31 in the CSS listing). This in itself is not necessarily a useful trick, because the image is then backwards, but replacing the background image (line 14 in the CSS listing) while it's flipped gives the illusion that you're looking at the back of the same image.

Of course you can use a pseduoclass other than hover - focus comes to mind as one that may be useful. Also, your CSS may need to be more complex in order to get everything positioned just where you want...or you may need to tweak it in other ways, but this will give you the general idea of how to create a simple animation that's tied to a real-world implementation.

If you want to see how it works, or if it works in your browser, if you're using the 'desktop' site, just hover over the 'help' icon (?) in the example below and if you're using a mobile version, tap on the 'help' icon (?) in the example below. Moving the hover outside the help icon (or tapping outside the 'help' icon) will flip the card back over.


?

Friday, January 1, 2016

Show Your Work: Markup and styles for showing code

It's been quite some time since I've posted. Everyone is busy, and has different priorities, and sometimes that leads to an erratic posting schedule. As another year ends, I thought I end it with a short post about something I do quite often...writing code samples online. Why this topic? Because it's one of the things that all UI engineers should be dealing with - writing about code is one of the ways we share knowledge, teaching and learning at the same time - and it's one of the ways we creatively express ourselves.

As for the more technical stuff about the topic - I've gone back and forth about how best to do it - how to mark it up so that it's still semantic but at the same time make the design look a little traditional and make the code example itself easy to reference, by saying something like "in Example 1, line 3 you'll see the reference to parseMarkerData". Typically, that means banding (each line an alternating color - like the old-style printer paper) and line numbers. The problem with line numbers is that either you typically use an ordered list (which has its semantic advantages) or somehow put the line numbers in the markup (which is not semantic). I don't like the ordered list, mostly because a list item is not necessarily an item - it may be more or less than an item - and the ordered list is typically very difficult to style because of all the built-in browser styles.

I, therefore, have been going with a slightly different approach...I've started using a BLOCKQUOTE tag (because I'm typically quoting a block of code) and a SPAN tag to identify portions of the quoted code. This allows me to use a 'header' to describe the code block as well as wrap the quoted code in a DIV tag to enable scrolling for large blocks and maintain semantics by using a CSS counter to show the line numbers. My code sample ends up looking something like this...

<blockquote class="code"><p class="header">Example 1</p>
  <div class="viewport">
    <span class="line">&lt;script&gt;</span>
    <span class="line">var terra = new d3.geo.earth(document.getElementById('map')), trans;</span>
    <span class="line"></span>
    <span class="line">terra.parseMarkerData('airport-data');</span>
    <span class="line">trans = document.getElementById('btnTransform');</span>
    <span class="line">trans.onclick = function(e) {</span>
    <span class="line">    var style = 'Equirectangular';
    <span class="line">    if (terra.style() === style) {</span>
    <span class="line">      style = '';</span>
    <span class="line">    }</span>
    <span class="line">    terra.style(style);</span>
    <span class="line'>  };</span>
    <span class="line">&lt;/script&gt;</span>
  </div>
</blockquote>

...and my CSS, with its use of pseudo classes (like nth-of-type and before) and a counter looks like this...

blockquote.code { counter-reset:line; border:2px solid rgb(51, 153, 187); border-radius:20px; box-shadow:4px 4px 4px rgba(51, 153, 187, 0.7); font-family:monospace; font-size:0.8em; margin: 0.5em; padding:10px; }
blockquote.code > p.header { border-bottom:1px solid rgb(192, 219, 229); font-size:1.2em; font-weight:bold; margin:0 0 0.2em 0; }
blockquote.code > div.viewport { max-height:20em;   overflow-y:auto; }
blockquote.code > div.viewport > span:nth-of-type(odd) { background-color:#efefef; }
blockquote.code > div.viewport > .line { display:block; }
blockquote.code > div.viewport > .line:before { display:inline-block; margin:0 1em 0 0; text-align:right; width:2em; }
blockquote.code > div.viewport > .line:before { counter-increment:line; content:counter(line); }

That's all there is to it. This combination ends up giving me something useful that looks decent. Something that looks like this...
If you want to see how this works in a real-world example, head on over to my D3 earth plugin example page where you'll find several uses of the code sample style.