Custom UI Elements Tutorial

Below, you will find some discussion of ways to customize certain HTML elements. Many of the elements you need to design for your app share properties discussed below. Keep in mind that these are just examples.

Instead of using the code explained below as is, please design your own custom widgets or controls.

Concepts & Definitions

Before showing you examples of customizition for HTML elements, here is an extremely concise theoretical discussion of terms and concepts related to interface design. In this project, you will design UI controls(1) providing user feedback(2) through state(3) transitions(4) triggered(5) through micro-interactions(6).

The highlighted keywords are explained below. It is important to share a language when talking about the stuff we talk about. Every field of human endavour has its technical terms. You should familiarize yourself with those of design. Here we are looking at a specific subset of those. I purposefully included more keywords than absolutely necessary in the sentence above so you get acquainted with a wider set of concepts. Words matter.

1. Control

This is an important word for you to know, but it is less clearly defined. A control is an object that can be manipulated by the user in an interface. A typical example is a navigation menu. The word control refers to the thing itself. It does not specify what type or style of thing it is. A site’s drop-down menu, picture carrousel, search box, are all controls. Note that controls are also called widgets. The words do not have exactly the same meaning, but they are often used interchangeably.

2. Feedback

We design interface elements and components to help the user of an app achieve what they want. Feedback is the way an app or system tells the user what is going on. To know that it worked when you clicked a button, the button itself or the presentation should visually change when you click on it. It is also a good idea to show a progress bar during long actions.* Programmatically, there is no need to show anything on the screen; the button has been cliked, the action has been triggered, the computer does it’s thing. But for the user, you want to provide feedback.

Lack of feedback is confusing. You know this from personal experience, when you click an OK button, and nothing happens. Did it work? Should I click again? In the app UI you design for this project, feedback will take the form of transitions and micro-animations between states.

* Note that although they remain useful for the user, and completely useless for the program itself, progress bars rarely show the actual progression of the computer’s process. They are psychological tools to help enhance the user’s patience, not faithful representations of what is happening. 🤯

3. State

A state is an occurance of feedback, it defines the appearance of an object at the different moments of an interaction. A button, like most controls, usually has many states with names like: stand or default, when it appears on the page; hover, when the mouse pointer passes over it; click or active, when the user clicks with the mouse or touches the screen at the location of the button; disabled, when a button is visible but inactive or unavailable. The designer should provide a different visual appearance for every state of a control.

4. Transition

A transition is usually a short animation that progressively blends the visual qualities of a control during the passage between two states. If a text field is white by default and red when there is an error, the transition is the passage between white and red when an error is triggered. There can be no transition, and the field will just instantly switch to red when there is an error. Or the colour of the field can transition more or less quickly between white and red. Transitions contribute to the user experience by smoothing the feedback.

This whole UI design project is founded on applying transitions.

5. Trigger

A trigger is the action that makes an event happen in user interaction design and in programming. An event can be triggered by a user action – click, touch, select, type — by hardware – copying a file, recording video with a camera – or by a software action – the end of a calculation, when a value becomes true.

The trigger is what starts the transition between states: user clicks, file is downloaded, item is added to DB, error happens, etc.

6. Micro-interaction

What you design and create for this project is generally called micro-interaction. State changes, transitions, feedback are all part of the overall concept of micro-interactions. Micro-interactions contribute to the user experience. They make the experience richer, more dramatic, more fascinating, and hopefully less stressful. For many years now, people have gotten used to micro-interactions and micro-animations. Interfaces that do not provide them seem cold and unpleasant.

More information

Here are a few links to additional resources. Check them out.

Watch this video

Read this article which is related to the video, and written by the same person: Alita Joyce.

You should also read this article.

Now that you have a better understanding of the concepts, you will find below specific suggestions to cusomize HTML elements. I focus on buttons and text fileds, but of course everything can be customized. And for your app, you need to customize every control.

Buttons

A button is a thing that the user can click or touch to validate a command, or to navigate an app, or to activate an option, or even to select a tool. There are several ways of creating buttons in HTML.

HTML provides tags for buttons. You can readily use the <button> tag. This will make a button that looks like this: . It has default properties, and it will look differently on different browsers. I’ve designed the clickable buttons as buttons in the sample app I gave you.

This type of button is natural, but sometimes it is a bit difficult to style the way you want. An alternative is to use a simple <a > tag (it’s called anchor), and make it look like a button using css.

<a> tag button

Notice how this reacts to the mouse. Also click on it for fun… Three states, shown in a single widget: stand + hover + click. The CSS is as follows. (This uses an id of #bttn that would be applied to the anchor tag.)

#bttn {
  display: inline-block;
  padding: 0.3em;
  background: #339;
  color: white;
  text-decoration: none;
  border-radius: 5px;
  transition: all 1s;
}
#bttn:hover {
  background: #393;
  box-shadow: 5px 5px 8px black;
}
#bttn:active {
  transition: none;
  box-shadow: 2px 2px 2px black;
}

You can see that designing a button is super easy.

If we wanted to make a disabled state for this button, we could do it like this. The CSS code follows.

<a> tag button

#bttn.disabled {
  display: inline-block;
  padding: 0.3em;
  background: white;
  color: #ccc;
  text-decoration: none;
  border-radius: 5px;
  border: solid 3px #ccc;
  pointer-events: none;
}

In the example’s code, I added a class .disabled to the #bttn element we used before. You can use any way you want to apply this state. Now for the code, I am sure you can see how the colours are different here. We also do not need other rules for other states because this is an inactive state. This state would have to be applied to the button by JavaScript in the case where the button is unused.

The one element that is different is the last property: pointer-events: none;. This turns off any event related to this element. So you don’t see the pointer mouse icon, and when you click nothing happens. With this, the button is truly disabled.

Text Input

Here we’ll play with a plain old text input field. There are several of those as well in the app. To start with, a text input looks like this.

<form action="#" autocomplete="off" id="textInput">
  <fieldset>
    <input id="first" type="text" name="first" required>
    <label for="first">First Name</label>
  </fieldset>
</form>
    

Note that I have included a <form> tag and a <fieldset> tag. These are not absolutely necessary to simply show the input. But if it were to be used, the input would need to be inside a form. You know this already. And we will use the fieldset for some fancy transitions later. Stay tuned!

The code above, as default, looks like this.

Now we can customize this thing. Let’s start with simple changes. The label is a just a text container. You can apply to it any property that affects typography: font-family, size, color, etc. The text box itself, the input, is like a block element, it has: border, background, box-shadow, etc. Notice that the label is after the input. This is because of the way we will use it. You could do it otherwise.

So let’s make the label blue (my default text colour on this page is grey). And let’s place it right below the field instead of on its right. Also, let’s set the field’s border so it is just a line on the bottom of the field instead of a box. More like a print form. Finally, let’s eliminate the border around the fieldset. You’ll need to place this CSS code inside a style tag to try it out.

Note that I did not change the width of the input. It is a bit too small for a real text field. In your app, you should consider the size of fields. But it does not matter here for our discussion.

#textInput fieldset {
  border: none;
}
#textInput label {
  color: #339;
  display: block;
}
#first {
  outline: none;
  border: none;
  border-bottom: solid #339 2px;
}
    

With the code above applied, it looks like this.

Now try to click on the field to type in it. You see how the colour, the border, etc. change? This is done with a transition between states in CSS. The code looks like this. (I’ve just put the two rules for the input field. This replaces the two rules with the same selector from the previous code block. Do not duplicate rules.)

#first {
  outline: none;
  border: none;
  border-bottom: solid #339 2px;
  transition: all 1s;
}
#first:focus { /*this is the focus state*/
  border-bottom: solid green 2px;
  background: lightgreen;
}

Let do something more fancy. We’ll put the label ‘inside’ the field, so it looks like a placeholder. And when you give the focus to the field, the label moves to the top and lets you write what you want.

This sounds complicated, but it is not that bad. The CSS is a little bit more elaborate. Here it is. I will explain it below. Again, the rules here that have selectors that already exist should not be duplicated. They should replace what you have already. You need to add the new rules.

#textInput fieldset {
  border: none;
  position: relative;
}
#textInput label {
  position: absolute;
  top: 1em;
  color: #339;
  display: block;
  transform-origin: left;
  transition: all 1s ease;
}
#first {
  outline: none;
  border: none;
  border-bottom: solid #339 2px;
  margin-top: 1em;
  transition: all 1s;
}
#first:focus, #first:valid {
  border-bottom: solid green 2px;
  background: lightgreen;
}
#first:focus ~ label, #first:valid ~ label {
  top: 0px;
  transform: scale(0.8, 0.8);
  color: green;
}

The first odd thing you will notice here is that we set the position: relative; for the fieldset. This is to allow us to then specify the absolute position of the label so we can animate the label’s position.

Next up, we set the position: obsolute; for the label, like I just mentioned. Then we position it so it appears inside the field: top is the property that positions an element from the top. We also set the transform-origin which determines from which side it will scale (we’ll get to that). And of course, we need to set a transition property so it animates the transition between the states.

The input #first is basically like it was in the previous step. The focus state of the input also remains the same. But you will notice that I have added a second selector: #first:valid to the rule. This determines the properties of the input when it has a value in it. We don’t want the label to move back into the field after the user has entered their value.

The last rule is a new one. And it is probably a selector you have never used. The ~ connector selects siblings: elements that have the same parent. This is why we need the label tag after the input in the HTML, so we can select it using this selector type. So #first:focus ~ label means: get the label element (tag selector) that is a sibling of the #first element, when this one has the :focus (when the keyboard insertion point is in it). So what happens to the label when the input gets the focus? It moves to top:0px; (no longer inside the field, but above it). We also scale it so it appears smaller. And we make it green, like the colour of the field on focus.

Note

I want you to notice how the colours in the examples I provide are similar. Notice how the stand states are all using #339 blue. Notice how the active states use #393 green. And most of the greys are #ccc. This is not a chance thing, it is not random. This is a decision, it is design. This makes the text fields and the buttons part of the same visual family, they use the same visual language.

I could have used other features to further emphasize this visual language: stroke thickness, box shape, line style, relative sizes, etc. It is part of your mandate to design every element of the interface as members of a system.