Hiding UI Elements

At the start of March 2019 I ran a poll on Twitter to see how devs hide UI elements. Here’s the tweet and results.

50% CSS "display:none",
5% HTML "hidden" attribute,
27% JS framework state,
18% Something else

Admittedly, not a very scientific sample size but it was enough to confirm my suspicion that very few people use the “hidden” attribute. I should probably call it a property rather than an attribute as it’s a Boolean and acts in a similar way to “disabled” or “required” which we often use on form elements. And, by contrast, the most common method seems to be to use the CSS “display:none”. Probably no great surprise to anyone.

I think it’s interesting to think about what we’re really doing when we hide an element. Is the visibility of the element just for screen users or for all users? Do we still want the element available for non visual media? Or is the content going to be used by another part of the page in some way? Does it need to be in the DOM at all or are we just keeping it there because it’s easier?

If we use JavaScript, either native or a framework, we can insert and remove elements as needed based on logic. If it’s playing no part in our document why not just leave it out altogether? This keeps the DOM light and performant and easier to work with. If you’re working with something like automated testing you can check for an element’s existence rather than trying to figure out if it’s visible or not.

If we use CSS to hide an element and respect the separation of concerns principle then are we saying that hiding this element is a presentational choice rather than a semantic one? Maybe we are hiding it, maybe temporarily, rather than denying its existence?

In the case where we want an element to be hidden in one medium and shown in another, CSS feels like the right choice. Whilst “display:none” and “visibility:hidden” are valid, other techniques like “height:0”, “opacity:0” or “left:9999px” feel very unclear in their intentions and too focused on the visual user.

The HTML “hidden” property is a more semantic choice. It is stating that this element is not to be considered when reading the document, whether that be on screen or via assistive technologies. It is about more than visibility and is probably badly named. Maybe “ignore” would have been more fitting? It is more about the state of the element and closer in meaning to the input[type=hidden] that we used to see in the days before Ajax.

If you take away the JavaScript and CSS – maybe some network issues, maybe the HTML gets copied elsewhere – the element stays hidden. The point is that it’s meant to be hidden, it’s not styling.

The “hidden” property is also easy to work with and change in JavaScript. In fact, it’s easier than using a CSS class as you don’t have to write any CSS and you know it will work regardless.

<p class="disclaimer" hidden>This is a disclaimer</p>

<script>
  const disclaimer = document.querySelector('.disclaimer');
  function showDisclaimer() {
    // with a CSS class
    disclaimer.classList.add('show');
    // with the hidden property
    disclaimer.hidden = false;
  }
</script>

Think about why your content is hidden and how it may be reused and choose the most appropriate method of hiding it (or removing it).

Making Icons Accessible

I’ve been using the excellent Font Awesome for a few years and it’s become part of almost every new design that I do. For a long time I’ve just slapped my icon down on the page, styled it and added a click event where needed. Job done.

Having spent some time looking a bit more deeply into accessibility, I can now see that this is not a great approach. There’s more to consider. If you can’t see it what is it actually doing?

Here’s how I approach using icons now. It may not be the perfect solution but it’s certainly a lot closer than most use cases I see. The way I use HTML depends on the use case.

If the icon is purely decorative – there in addition to text, e.g. a floppy disk icon next to the word “Save” on a button, then I think we can reasonably just forget about it and hide it for non screen users. A simple aria-hidden=”true” attribute should do.

<button><i class="fa fa-save" aria-hidden="true"></i> Save</button>

If it is there as an indicator, in place of a label, like where a hotel might have icons for TV, bath, etc. then we can use an <span> to wrap it. Inside the span we add our icon and another span with a text alternative. We show the icon and hide the inner span for screens, show the text only for other media.

Finally, if the icon is interactive and acts like a link or button, let’s make it a link or button. Like the previous example, use the <button> or <a> tag to wrap the icon and a span text alternative and show/hide for the appropriate media. This has the added bonus of making it possible to tab to the icon and so use just the keyboard to navigate the page. It also handles the icon’s active state and visited in the case of a link.

Alternatively, if you didn’t want to add a span with text inside your button or link, you could use the aria-label attribute to provide a text alternative.

One little tip. If you use an icon inside a link or button, do not leave whitespace between the outer wrapper element and the inner icon as you may get unwanted effects in the styling, such as underlined spaces either side of your icon. Keep it tight.

To DOM or Not to DOM?

I’m trying to work out when it’s best to put attributes in the DOM and when it’s best to just leave them in JavaScript objects. This is going to be hard to explain so bear with me.

Let’s suppose we have a list of users on a page. Each user has a number of properties, not things we’d display like name, age and gender but hidden things like permissions, e.g. isAdmin, canComment, isManager, etc. These properties are going to be used in logic to determine how things are displayed on screen – maybe an extra bit of detail or an icon. Just as an example, if canComment is true then a speech bubble icon will appear.

The basic HTML might look something like this:

<ul>
  <li id="001" class="user">John</li>
  <li id="002" class="user">Paul</li>
  <li id="003" class="user">George</li>
</ul>

Behind this is a JavaScript object, like this:

var users = [
  {
    id: '001',
    name: 'John',
    canComment: true
  },
  {
    id: '002',
    name: 'Paul',
    canComment: false
  },
  {
    id: '003',
    name: 'George',
    canComment: false
  }
];

So, user John is allowed to comment and we want to show an icon. There are 2 approaches:

  1. Use the DOM

    We could add the icon inside each <li> and then add a class (class=”user can-edit”) or a data-attribute (data-can-edit) to the <li> and use CSS to display it as appropriate, e.g. .user[data-can-edit] .icon { display: inline-block }.

  2. Use JavaScript

    Or, we could write a JavaScript function to filter the objects to just those with canComment set to true, get their ids, and then loop through the list items adding the icon HTML when the ids match the filtered list.

The first approach puts the property into the DOM, puts the icon into the DOM and then uses CSS to show/hide it. It feels easy. The icon is always sat there waiting, like an unchecked checkbox, only shown when needed (checked). There is still logic but it’s done up front. The DOM is actually human readable and it’s easy to see which users can and can’t edit for debugging purposes. I see this approach used a lot, including the hidden DOM elements, usually because of the way templates or components are used. It’s easier to include it and pass a property to toggle whether or not it displays. It also means that if we want to change the property during the lifecycle of the page, e.g. take away John’s commenting permission, it’s minimal change to the DOM.

The second approach only touches the DOM to insert the icon where needed. It does all the logic in JavaScript and the output in the DOM reflects what the user actually sees on screen. There are no hidden elements. This has advantages when it’s scaled up, in that it keeps the DOM lighter and there’s no waste. The JavaScript is incredibly fast in modern browsers so the functions won’t slow anything down, especially if using .filter(), map(), etc. The trick here is not to loop through and add the icons one at a time but to run through building the whole list and just doing the one insert or replace operation. This makes the DOM less readable as all the canComment data is in JavaScript.

So, is it better to use the DOM for data or keep it in JavaScript?

 

Learning the Right Things

With so much happening so fast knowing what new tech to learn next can be difficult. Where should you invest your time and energy? What if you spend ages learning the shiny new framework and it’s gone within 2 years?

There are a lot of trends and a lot of new-fangled things do come and go. How do you spot the ones that are going to stick around. It’s not easy – you kind of have to go with the flow, not swim against the tide (2 water based metaphors in one sentence, tut).

In front end development there are currently a few big JavaScript frameworks – Angular, React and Vue. It seems obvious to me that none of these are going away any time soon. Which do you choose? It really doesn’t matter. Learning one in depth, finding its powers and limitations, will help you learn the others or other future technologies.

If you’re really not sure where to turn I’d focus on core learning. In the front-end world, learn plain JavaScript. With ES2015 and newer versions than that emerging there’s still plenty to take on and perfect. That knowledge will always be useful.

I guess my short answer would be to favour the evergreen HTML, CSS and JavaScript over associated tech like Pug, Sass, TypeScript, etc. As the core technologies get better over time these current convenience technologies may one day not be needed.

One word answer. JavaScript. :)

Lazy HTML :(

Poking through other developers’ HTML pages I sometimes come across markup like this:

<br>
<br>
<br>

It’s generally used to just add some space between block elements. My instinctive reaction is a mixture of horror and disbelief. I can’t remove it quick enough and get some CSS to control it instead.

Thinking about it a little deeper, this tag gets misused a lot. There’s a big difference between a semantic break between 2 bits of content and just shifting something down a line because it looks better at the time. The example above using several line breaks consecutively is, to my mind, just plain wrong. A break is used to separate content and its semantic meaning here is trying to separate other breaks.

To be fair to the other developers there’s a good chance it’s some visual editor doing a bad job rather than it being hand coded this way but the result is the same.

HTML should be about conveying the meaning of the content, not just a way of putting text on screen. Adding gaps or breaks between bits of content needs to be considered too.

Margin vs Padding

We get a similar situation with margin and padding. Some developers just use these interchangeably to put a gap between elements but this feels wrong to me. Even though this is purely styling rather than content and doesn’t need to worry about semantics in the same way, it’s still a matter of how you view a particular element. If it appeared in another context, would it always have this margin or padding? I think we should be designing chunks of content as independent elements, which can be dropped into a page ready to go without the need for excessive styling for their context.