Editor’s Note: Designers could learn how to code, and developers could learn how to design. Sometimes it might not be an option. In this article, the author makes a suggestion to designers without coding skills on how to start crafting code. You might want to take the suggested tool with a grain of salt (or not) but the idea might be worth looking into.
Designers have widely adopted HTML and CSS for a while now. They usually feel comfortable enough to implement their own designs, at least in a static form. However, they’re often intimidated by JavaScript — and rightly so! HTML and CSS are declarative and, I’d argue, closer to design than programming.
Further Reading on SmashingMag:
- Team Collaboration And Closing Efficiency Gaps In Responsive Design
- Designers And Developers Playing Nice
- Developers “Own” The Code, Designers “Own” The Experience?
- How To Effectively Communicate With Developers
JavaScript, on the other hand, is “real” programming. This means you not only have to learn a whole new and complex syntax but also have to “learn how to think.” The barriers to entry are high and prevent many designers from taking the plunge. uilang tries to fix that.
This article will introduce you to uilang’s philosophy and syntax. We’ll start with a simple example to get you comfortable with the basics, before moving to something more exciting. At the end of this tutorial, you’ll (hopefully!) be able to code many typical interface widgets, such as popovers, tabs, overlays and much, much more.
The Bridge Between Designers And Developers
I strongly believe that designers should code the interfaces they design. They shouldn’t necessarily write production-ready code, but they should design the behaviors. Designers love these things. They could spend hours tweaking an animation delay or finding the right cubic-bezier curve. They usually just lack some technical skills to do so.
uilang tries to facilitate the communication between designers and developers by giving designers an extremely simple tool to prototype their interfaces. uilang reads like plain English, uses a one-line syntax declared right in the HTML and provides very few options in order to make its learning process and adoption as fast and easy as possible. We’ll cover the syntax in detail later, but here’s a sneak peek at it:
clicking on "button" toggles class "visible" on "div"
uilang is not exclusively a prototyping tool, though. It can safely be used on production websites to create, for example, tabs, photo galleries, popovers and more. Let’s see how it works!
Getting Started
uilang is based on a dead simple principle: manipulating classes on your elements. By just adding and removing classes when something is clicked, we can show, hide, transform and animate elements using CSS. This simple logic gives you endless possibilities. Let’s explore one of them by creating a simple notification banner like this:
See the Pen bNWaVz by Benjamin De Cock (@bdc) on CodePen.
We’ll start with the HTML markup, which is pretty straightforward:
<div id="notification">
<p>You have 3 unread messages.</p>
<button class="hide">Hide</button>
</div>
We’ll now use uilang to define a simple behavior: When the user clicks on an element that has a hide
class, we’ll add a hidden
class to the element that has a notification
ID. The translation in actual uilang code looks almost the same as the explanation above:
clicking on ".hide" adds class "hidden" on "#notification"
This line of code should be written in a simple <code>
element, right in the HTML. uilang will automatically find the <code>
element containing your code and will ignore other <code>
elements that you might have on the page. Additionally, you’ll have to download and insert the uilang.js library (1 KB).
While both your <code>
and <script>
elements can
theoretically be inserted anywhere on the page, it's recommended to place them at the very end of the document, just before the closing </body>
tag:
<body>
<!-- Your content -->
<script src="uilang.js"></script>
<code>
<!-- Your uilang code -->
</code>
</body>
By respecting that order, you're making sure to reach the best rendering performance. Thereby, your final HTML markup for the notification banner will look like this:
<body>
<div id="notification">
<p>You have 3 unread messages.</p>
<button class="hide">Hide</button>
</div>
<script src="uilang.js"></script>
<code>
clicking on ".hide" adds class "hidden" on "#notification"
</code>
</body>
We’re almost done! Now that the behavior has been defined, we’ll rely on CSS to fade out that notification banner once the hidden
class has been applied to it:
#notification {
transition: .8s
}
#notification.hidden {
opacity: 0
}
Congrats! You now know how to code! You might not realize it yet, but this simple logic will let you build a wide range of widgets and interactions. Let’s have a closer look at the options provided by the syntax.
Syntax
The syntax can be split into four parts:
clicking on ".hide"(1) adds(2) class "hidden"(3) on "#notification"(4)
- any CSS selector
adds
,removes
ortoggles
- any class name
- any CSS selector or the
target
keyword (which selects the clicked element)
That’s all you need to learn. Keep in mind that uilang is basically just HTML, so you can comment the code similarly:
<code>
<!-- I'm a comment -->
clicking on ".hide" adds class "hidden" on "#notification"
<!-- I'm another comment -->
clicking on "li a:first-child" toggles class "active" on "target"
</code>
Please note that uilang only supports click events. Hover effects can usually be achieved in CSS, and other events are simply beyond the scope of this language.
We’ve now covered the basics of uilang. It’s time to build a more advanced demo!
Apple-Like Explore Menu
We’ll create a collapsible, animated menu similar to the kind you can find on Apple’s website. Check out the demo to see the result.
HTML Markup
Nothing fancy, really, just a simple link to toggle the navigation, and the nav
element containing our list of links:
<a class="explore" href="#">Explore</a>
<nav>
<ul>
<li>
<a href="#"><img alt src="images/1.jpg">West Coast</a>
<li>
<a href="#"><img alt src="images/2.jpg">Venice</a>
<li>
<a href="#"><img alt src="images/3.jpg">Peyto Lake</a>
<li>
<a href="#"><img alt src="images/4.jpg">Iceland</a>
<li>
<a href="#"><img alt src="images/5.jpg">Golden Gate</a>
</ul>
</nav>
Now, adding the toggling behavior with uilang will be extremely simple:
<code>
clicking on ".explore" toggles class "open" on "nav"
</code>
We’ll then use this open
class in our style sheet to show and hide the nav
. Just before we do that, let’s add a few things to complete our HTML markup: a meta tag for mobile users, the link to our style sheet and, obviously, the uilang.js library! The whole HTML might now look like this:
<!doctype html>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1">
<title>Explore menu</title>
<link rel="stylesheet" href="style.css">
<a class="explore" href="#">Explore</a>
<nav>
<ul>
<li>
<a href="#"><img alt src="images/1.jpg">West Coast</a>
<li>
<a href="#"><img alt src="images/2.jpg">Venice</a>
<li>
<a href="#"><img alt src="images/3.jpg">Peyto Lake</a>
<li>
<a href="#"><img alt src="images/4.jpg">Iceland</a>
<li>
<a href="#"><img alt src="images/5.jpg">Golden Gate</a>
</ul>
</nav>
<script src="uilang.js"></script>
<code>
clicking on ".explore" toggles class "open" on "nav"
</code>
Note: For those wondering about the brevety of the code, keep in mind HTML5 considers as optional the <html>
, <head>
and <body>
tags. Feel free to adopt a different style if you have another preference!
CSS: Where The Magic Happens
As always with uilang, the interesting parts of the code are in the style sheet. uilang’s role is exclusively to define the behaviors, not to execute them.
Let’s start by styling and positioning our elements, so that our navigation is ready to be manipulated with uilang. I won’t go into much detail — I assume you’re already comfortable with basic, standard CSS — so I’ve only commented some parts of the code. Please note that irrelevant style declarations, such as for fonts and colors, have been omitted for clarity.
body {
background: #f3f3f3;
}
.explore {
/* Make sure the Explore link stays above the nav */
position: absolute;
z-index: 1;
}
nav {
background: #fff;
box-shadow: 0 1px 2px rgba(0,0,0,.15);
}
nav ul {
/* Allow mobile-friendly horizontal scrolling when the browser isn't wide enough */
overflow: auto;
-webkit-overflow-scrolling: touch;
/* Force the thumbs to display in a row */
white-space: nowrap;
padding: 80px 40px 40px;
}
nav li {
display: inline-block;
}
Onto the interesting part: coding the toggling behavior! We’ll need two things:
- By default, the
nav
and the thumbs should be hidden. This means we need to initially slide up thenav
and make thenav
and images transparent. - When the
open
class defined in our uilang code is applied to thenav
, we need to reverse the default state: slide down thenav
and fade in everything.
Step 1 is pretty easy: We’ll use translateY(-100%)
to slide the nav
up, opacity: 0;
to hide the nav
and images, and transition
to animate these elements when the class is applied.
nav, nav li {
opacity: 0;
}
nav {
-webkit-transform: translateY(-100%);
transform: translateY(-100%);
transition: .4s;
}
nav li {
transition: .3s;
}
This is not immediately related to uilang but, because uilang does rely on CSS for transitions and animations, we should probably remember a few important principles:
- You can safely and smoothly animate only two properties:
opacity
andtransform
. Force yourself to stick with them. - When only the duration is specified in the
transition
shorthand property, all properties that might change in future will be animated and will useease
as their timing function. - Keep your animations fast! Animations are important because they help users to understand the flow between two states, but they should never get in the way. A good
transition-duration
is usually between 200 and 800 milliseconds. - While standard easing keywords are sometimes acceptable (such as with this demo), custom cubic-bezier curves are often preferable. Many tools enable you to find the right curve, such as Matthew Lein’s Ceaser.
- The examples in this tutorial use CSS transitions, but feel free to use CSS animations instead when needed! The principle is exactly the same, and keyframes might provide a finer level of control.
Now that our default state has been set up, we can go to step 2 and code the “open” state, which basically means reverting step 1 to the default values for the open
class:
nav.open, nav.open li {
opacity: 1;
-webkit-transform: none;
transform: none;
}
nav.open li {
/* Wait for the nav to slide down a bit before starting the animation on the thumbs */
transition-delay: .3s;
}
Boom! You now have a fully functional animated navigation menu. A few things are missing that would make it truly great, though, starting with the scale animation on the images. If you look closely at the demo, you’ll notice that the images not only fade in when they appear but also zoom in a little. Let’s add that behavior by making them slightly smaller by default:
nav li {
-webkit-transform: scale(.8);
transform: scale(.8);
}
We’ve already defined that nav.open li
will reverse to transform: none;
and that all properties will animate, so there’s nothing more to add.
Good! We’re almost done, but one important thing is missing: changing the icon on the “Explore” link when the nav
is open or closed. To do that, we’ll need to define a new rule in our uilang code. We’re currently toggling an open
class on the navigation to show and hide it; we’ll need to do something similar for the link itself.
<code>
clicking on ".explore" toggles class "close" on "target"
clicking on ".explore" toggles class "open" on "nav"
</code>
Here, target
represents the clicked element. In this case, you could have just reused .explore
instead of target
. However, that wouldn’t be the same if you had multiple “Explore” links on the same page (.explore
matches any “Explore” link, whereas target
selects only the clicked “Explore” link).
Back to the CSS. We’re going to use pseudo-elements to display our icons. .explore::before
will represent our grid icon (visible when the navigation is closed), and .explore::after
will display the cross when the navigation is open. Both will benefit from the same transition-duration
.
.explore::before, .explore::after {
content: "";
position: absolute;
left: 0;
transition: .25s;
}
.explore::before {
background: url(grid.svg);
}
.explore::after {
background: url(close.svg);
/* Hidden and scaled up by default */
opacity: 0;
-webkit-transform: scale(1.8);
transform: scale(1.8);
}
The grid icon is already visible; the close icon is hidden but correctly positioned, ready to fade in as soon as “Explore” is clicked. We just have to reverse the default state when the close
class defined in our uilang code is applied to .explore
:
/* When the nav is open, hide and rotate the grid icon… */
.explore.close::before {
opacity: 0;
-webkit-transform: rotate(45deg) scale(.8);
transform: rotate(45deg) scale(.8);
}
/* … and display the close icon */
.explore.close::after {
opacity: 1;
-webkit-transform: none;
transform: none;
}
That’s it! We’ve achieved this pretty cool effect with just two lines of uilang and a few CSS declarations. Note that, while the uilang code might not be used in production by the developers you collaborate with, your CSS is production-ready. Most of the prototyping tools out there force you to build mockups outside of the actual HTML and CSS, which forces developers to reimplement your animations, delays, easings and so on. Details get lost all the time. With uilang, developers can just reuse your CSS and focus exclusively on reimplementing the logic in JavaScript.
Icing On The Cake
As a bonus, let’s end this tutorial by having some fun with CSS! The grid and close icons that we’re using on the “Explore” link are actually pretty simple, and using images for them (as we’re doing) would be a shame when we could just draw them in CSS. Let’s do this!
The grid icon is the most interesting one. While it might initially seem counterintuitive, we’re going to use gradients to draw it. The idea is that each of the nine squares will be drawn as a gradient from black to black. When you create a CSS gradient, you’re basically generating an image on the fly. This (background) image can then be sized and positioned anywhere.
Here’s the translation in CSS (available on CodePen):
.explore::before {
width: 13px;
height: 13px;
background-image: linear-gradient(#000, #000),
linear-gradient(#000, #000),
linear-gradient(#000, #000),
linear-gradient(#000, #000),
linear-gradient(#000, #000),
linear-gradient(#000, #000),
linear-gradient(#000, #000),
linear-gradient(#000, #000),
linear-gradient(#000, #000);
background-position: 0 0, 50% 0, 100% 0,
0 50%, 50% 50%, 100% 50%,
0 100%, 50% 100%, 100% 100%;
background-repeat: no-repeat;
background-size: 3px 3px;
}
It’s verbose and arguably crazy, but keep in mind that, while we’re essentially doing it for fun, this technique comes with real advantages, the most important one being undoubtedly the HTTP request you save from not requesting a file.
The close icon is much simpler but still requires some tricks to make it look great. We’ll use a similar technique: drawing a gradient from black to black for each bar of the cross in order to form a plus sign, then rotating the plus to make it look like a cross. To prevent the lines from looking jagged because of the 45-degree rotation, we’ll scale up the icon a little using the transform
property, which provides us with decent antialiasing.
.explore::after {
width: 11px;
height: 11px;
background-image: linear-gradient(#000, #000),
linear-gradient(#000, #000);
background-position: 50% 0, 0 50%;
background-repeat: no-repeat;
background-size: 1px 100%, 100% 1px;
-webkit-transform: rotate(45deg) scale(1.4);
transform: rotate(45deg) scale(1.4);
}
Go Create!
CSS is powerful, performant yet remarkably easy to use. uilang wants to stay invisible in your workflow and act as a gateway to using CSS to code interactions. After all, CSS might be the best “user interface” for creating prototypes.
Resources
- uilang
- uilang, GitHub
- The Educational Side of uilang: Or How to De-Dramatize Getting Into Programming,” Benjamin De Cock
Explains the philosophy behind uilang - uilang Transpiler
Transpiles uilang to JavaScript - “Sublime Text Snippet for uilang,” Zack Cote