s sideways (with a little assist from our new friend, the viewport-width unit, not that he was strictly necessary). All we need to know is how many pages we have. (And, boy, wouldn’t it be nice to be able to know that without having to predetermine it or use JavaScript?)
.window {
overflow: hidden;
width: 100%;
}
.pages {
width: 200vw;
}
.page {
float: left;
overflow: hidden;
width: 100vw;
}
If you look carefully, you’ll see that the conceit we’ll use in the rest of the demos is in place. Despite the document containing multiple pages, only one is visible at any given time. This allows us to keep the user focused on the task (or content) at hand.
By the way, you’ll need to use a modern, WebKit-based browser for these demos. I recommend downloading the WebKit nightly builds, Chrome Canary, or being comfortable with setting flags in Chrome.
A horizontally paginated site, with transitions
Ah, here’s the rub. We have functional navigation, but precious few cues for the user. It’s not much good shoving the visitor around various parts of the document if they don’t get the pleasant whooshing experience of the journey. You might be thinking, what about that new CSS selector, target-something…? Well, my friend, you’re on the right track. Let’s test it. We’re going to need to use a bit of sleight of hand. While we’d like to simply offset the containing element by the number of pages we’re moving (like we did on Massive), CSS alone can’t give us that information, and that means we’re going to need to fake it by expanding and collapsing pages as you navigate. Here are the bits we’re going to need:
.page {
-webkit-transition: width 1s; // Naturally you're going to want to include all the relevant prefixes here
float: left;
left: 0;
overflow: hidden;
position: relative;
width: 100vw;
}
.page:not(:target) {
width: 0;
}
Ah, but we’re not fooling anyone with that trick. As soon as you move beyond a single page, the visitor’s disbelief comes tumbling down when the linear page transitions are unaffected by the distance the pages are allegedly traveling. And you may have already noticed an even more fatal flaw: I secretly linked you to the first page rather than the unadorned URL. If you visit the same page with no URL fragment, you get a blank screen. Sure, we could force a redirect with some server-side trickery, but that feels like cheating. Perhaps if we had the CSS4 subject selector we could apply styles to the parent based on the child being targeted by the URL. We might also need a few more abilities, like determining the total number of pages and having relative sibling selectors (e.g. nth-sibling), but we’d sure be a lot closer.
A horizontally paginated site, with transitions – no cheating
Well, what other cards can we play? How about the checkbox hack? Sure, it’s a garish trick, but it might be the best we can do today. Check it out.
label {
cursor: pointer;
}
input {
display: none;
}
input:not(:checked) + .page {
max-height: 100vh;
width: 0;
}
Finally, we can see the first page thanks to the state we are able to set on the appropriate radio button. Of course, now we don’t have URLs, so maybe this isn’t a winning plan after all. While our HTML and CSS toolkit may feel primitive at the moment, we certainly don’t want to sacrifice the addressability of the web. If there’s one bedrock principle, that’s it.
A horizontally paginated site, with transitions – no cheating and a gorgeous homepage
Gorgeous may not be the right word, but our little magazine is finally shaping up. Thanks to the CSS regions spec, we’ve got an exciting new power, the ability to begin an article in one place and bend it to our will. (Remember, your everyday browser isn’t going to work for these demos. Try the WebKit nightly build to see what we’re talking about.) As with the rest of the examples, we’re clearly abusing these features. Off-canvas layouts (you can thank Luke Wroblewski for the name) are simply not considered to be normal patterns… yet.
Here’s a quick look at what’s going on:
.excerpt-container {
float: left;
padding: 2em;
position: relative;
width: 100%;
}
.excerpt {
height: 16em;
}
.excerpt_name_article-1,
.page-1 .article-flow-region {
-webkit-flow-from: article-1;
}
.article-content_for_article-1 {
-webkit-flow-into: article-1;
}
The regions pattern is comprised of at least three components: a beginning; an ending; and a source. Using CSS, we’re able to define specific elements that should be available for the content to flow through. If magazine-style layouts are something you’re interested in learning more about (and you should be), be sure to check out the great work Adobe has been doing.
Looking forward, and backward
As designers, builders, and consumers of the web, we share a desire to see the usability and enjoyability of websites continue to rise. We are incredibly lucky to be working in a time when a three-month-old website can be laughably outdated. Our goal ought to be to improve upon both the weaknesses and the strengths of the web platform. We seek not only smoother transitions and larger canvases, but fine-grained addressability. Our URLs should point directly and unambiguously to specific content elements, be they pages, sections, paragraphs or words. Moreover, off-screen design patterns are essential to accommodating and empowering the multitude of devices we use to access the web. We should express the desire that interpage links take advantage of the CSS transitions which have been put to such good effect in every other aspect of our designs. Transitions aren’t just nice to have, they’re table stakes in the highly competitive world of native applications.
The tools and technologies we have right now allow us to create smart, beautiful, useful webpages. With a little help, we can begin removing the seams and sutures that bind the web to an earlier, less sophisticated generation.",2012,Nathan Peretic,nathanperetic,2012-12-21T00:00:00+00:00,https://24ways.org/2012/infinite-canvas-moving-beyond-the-page/,code
236,Extreme Design,"Recently, I set out with twelve other designers and developers for a 19th century fortress on the Channel Island of Alderney. We were going to /dev/fort, a sort of band camp for geeks. Our cohort’s mission: to think up, build and finish something – without readily available internet access.
Alderney runway, photo by Chris Govias
Wait, no internet?
Well, pretty much. As the creators of /dev/fort James Aylett and Mark Norman Francis put it: “Imagine a place with no distractions – no IM, no Twitter”. But also no way to quickly look up a design pattern, code sample or source material. Like packing for camping, /dev/fort means bringing everything you’ll need on your back or your hard drive: from long johns to your favourite icon set.
We got to work the first night discussing ideas for what we wanted to build. By the time breakfast was cleared up the next morning, we’d settled on Russ’s idea to make the Apollo 13 (PDF) transcript accessible. Days two and three were spent collaboratively planning (KJ style) what features we wanted to build, and unravelling the larger UX challenges of the project. The next five days were spent building it. Within 36 hours of touchdown at Southampton Airport, we launched our creation: spacelog.org
The weather was cold, the coal fire less than ideal, food and supplies a hike away, and the process lightning-fast. A week of designing under extreme circumstances called for an extreme process. Some of this was driven by James’s and Norm’s experience running these things, but a lot of it materialised while we were there – especially for our three-strong design team (myself, Gavin O’ Carroll and Chris Govias) who, though we knew each other, had never worked together as a group in this kind of scenario before.
The outcome was a pretty spectacular process, with a some key takeaways useful for any small group trying to build something quickly.
What it’s like inside the fort
/dev/fort has the pressure and pace of a hack day without being a hack day – primarily, no workshops or interruptions‚ but also a different mentality. While hack days are typically developer-driven with a ‘hack first, design later (if at all)’ attitude, James was quick to tell the team to hold off from writing any code until we had a plan. This put a healthy pressure on the design and product folks to slash through the UX problems before we started building.
While the fort had definitely more of a hack day feel, all of us were familiar with Agile methods, so we borrowed a few useful techniques such as morning stand-ups and an emphasis on teamwork. We cut some really good features to make our launch date, and chunked the work based on user goals, iterating as we went.
What made this design process work?
A golden ratio of teams
My personal experience both professionally and in free-form situations like this, is a tendency to get/hire a designer. Leaders of businesses, founders of start-ups, organisers of events: one designer is not enough! Finding one ace-blooded designer who can ‘do everything’ will always result in bottleneck and burnout. Like the nuances between different development languages, design is a multifaceted discipline, and very few can claim to be equally strong in every aspect. Overlap in skill set will result in a stronger, more robust interface.
More importantly, however, having lots of designers to go around meant that we all had the opportunity to pair with developers, polishing the details that don’t usually get polished. As soon as we launched, the public reception of the design and UX was overwhelmingly positive (proof!). But also, a lot of people asked us who the designer was, attributing it to one person.
While it’s important to note that everyone in our team was multitalented (and could easily shift between roles, helping us all stay unblocked), the golden ratio James and Norm devised was two product/developer folks, three interaction designers and eight developers.
photo by Ben Firshman
Equality inside the fortress walls
Something magical about the fort is how everyone leaves the outside world on the drawbridge. Job titles, professional status, Twitter followers, and so on. Like scout camp, a mutual respect and trust is expected of all the participants. Like extreme programming, extreme design requires us all to be equal partners in a collaborative team. I think this is especially worth noting for designers; our past is filled with the clear hierarchy of the traditional studio system which, however important for taste and style, seems less compatible with modern web/software development methods.
Being equal doesn’t mean being the same, however. We established clear roles and teams for ourselves on the second day, deferring to that person when a decision needed to be made. As the interface coalesced, the designers and developers took ownership over certain parts to ensure the details got looked after, while staying open to ideas and revisions from the rest of the cohort.
Create a space where everyone who enters is equal, but be sure to establish clear roles. Even if it’s just for a short while, the environment will be beneficial.
photo by Ben Firshman
Hang your heraldry from the rafters
Forts and castles are full of lore: coats of arms; paintings of battles; suits of armour. It’s impossible not to be surrounded by these stories, words and ways of thinking. Like the whiteboards on the walls, putting organisational lore in your physical surroundings makes it impossible not to see.
Ryan Alexander brought some of those static-cling whiteboard sheets which were quickly filled with use cases; IA; team roles; and, most importantly, a glossary. As soon as we started working on the project, we realised we needed to get clear on what certain words meant: what was a logline, a range, a phase, a key moment? Were the back-end people using these words in the same way design and product was? Quickly writing up a glossary of terms meant everyone was instantly speaking the same language. There was no “Ah, I misunderstood because in the data structure x means y” or, even worse, accidental seepage of technical language into the user interface copy.
Put a glossary of your internal terminology somewhere big and fat on the wall. Stand around it and argue until you agree on what it says. Leave it up; don’t underestimate the power of ambient communication and physical reference.
Plan more, download less
While internet is forbidden inside the fort, we did go on downloading expeditions: NASA photography; code documentation; and so on. The project wouldn’t have been possible without a few trips to the web. We had two lists on the wall: groceries and supplies; internets – “loo roll; Tom Stafford photo“.
This changed our usual design process, forcing us to plan carefully and think of what we needed ahead of time. Getting to the internet was a thirty-minute hike up a snow covered cliff to the town airport, so you really had to need it, too.
The path to the internet
For the visual design, especially, this resulted in more focus up front, and communication between the designers on what assets we required. It made us make decisions earlier and stick with them, creating less distraction and churn later in the process.
Try it at home: unplug once you’ve got the things you need. As an artist, it’s easier to let your inner voice shine through if you’re not looking at other people’s work while creating.
Social design
Finally, our design team experimented with a collaborative approach to wireframing. Once we had collectively nailed down use cases, IA, user journeys and other critical artefacts, we tried a pairing approach. One person drew in Illustrator in real time as the other two articulated what to draw. (This would work equally well with two people, but with three it meant that one of us could jump up and consult the lore on the walls or clarify a technical detail.) The result: we ended up considering more alternatives and quickly rallying around one solution, and resolved difficult problems more quickly.
At a certain stage we discovered it was more efficient for one person to take over – this happened around the time when the basic wireframes existed in Illustrator and we’d collectively run through the use cases, making sure that everything was accounted for in a broad sense. At this point, take a break, go have a beer, and give yourself a pat on the back.
Put the files somewhere accessible so everyone can use them as their base, and divide up the more detailed UI problems, screens or journeys. At this level of detail it’s better to have your personal headspace.
Gavin called this ‘social design’. Chatting and drawing in real time turned what was normally a rather solitary act into a very social process, with some really promising results. I’d tried something like this before with product or developer folks, and it can work – but there’s something really beautiful about switching places and everyone involved being equally quick at drawing. That’s not something you get with non-designers, and frequent swapping of the ‘driver’ and ‘observer’ roles is a key aspect to pairing.
Tackle the forest collectively and the trees individually – it will make your framework more robust and your details more polished. Win/win.
The return home
Grateful to see a 3G signal on our phones again, our flight off the island was delayed, allowing for a flurry of domain name look-ups, Twitter catch-up, and e-mails to loved ones. A week in an isolated fort really made me appreciate continuous connectivity, but also just how unique some of these processes might be.
You just never know what crazy place you might be designing from next.",2010,Hannah Donovan,hannahdonovan,2010-12-09T00:00:00+00:00,https://24ways.org/2010/extreme-design/,process
73,How to Make Your Site Look Half-Decent in Half an Hour,"Programmers like me are often intimidated by design – but a little effort can give a huge return on investment. Here are one coder’s tips for making any site quickly look more professional.
I am a programmer. I am not a designer. I have a degree in computer science, and I don’t mind Comic Sans. (It looks cheerful. Move on.)
But although I am a programmer, I want to make my sites look attractive. This is partly out of vanity, and partly realism. Vanity because I want people to think my work is good, and realism because the research shows that people won’t think a site is credible unless it also looks attractive.
For a very long time after I became a programmer, I was scared of design. Design seemed to consist of complicated rules that weren’t written down anywhere, plus an unlearnable sense of taste, possessed only by a black-clad elite.
But a little while ago, I decided to do my best to hack what it took to make my own projects look vaguely attractive. And although this doesn’t come close to the effect a professional designer could achieve, gathering these resources for improving a site’s look and feel has been really helpful.
If I hadn’t figured out some basic design shortcuts, it’s unlikely that a weekend hack of mine would have ended up on page three of the Daily Mail. And too often now, I see excellent programming projects that don’t reach the audience they deserve, simply because their design doesn’t match their execution.
So, if you are a developer, my Christmas present to you is this: my own collection of hacks that, used rightly, can make your personal programming projects look professional, quickly. None are hard to learn, most are free, and they let you focus on writing code.
One thing to note about these tips, though. They are a personal, pragmatic compilation. They are suggestions, not a definitive guide. You will definitely get better results by working with a professional designer, and by studying design more deeply.
If you are a designer, I would love to hear your suggestions for the best tools that I’ve missed, and I’d love to know how we programmers can do things better.
With that, on to the tools…
1. Use Bootstrap
If you’re not already using Bootstrap, start now. I really think that Bootstrap is one of the most significant technical achievements of the last few years: it democratizes the whole process of web design.
Essentially, Bootstrap is a a grid system, with a bunch of common elements. So you can lay your site out how you want, drop in simple elements like forms and tables, and get a good-looking, consistent result, without spending hours fiddling with CSS. You just need HTML.
Another massive upside is that it makes it easy to make any site responsive, so you don’t have to worry about writing media queries. Go, get Bootstrap and check out the examples. To keep your site lightweight, you can customize your download to include only the elements you want.
If you have more time, then Mark Otto’s article on why and how Bootstrap was created at Twitter is well worth a read.
2. Pimp Bootstrap
Using Bootstrap is already a significant advance on not using Bootstrap, and massively reduces the tedium of front-end development. But you also run the risk of creating Yet Another Bootstrap Site, or Hack Day Design, as it’s known.
If you’re really pressed for time, you could buy a theme from Wrap Bootstrap. These are usually created by professional designers, and will give a polish that we can’t achieve ourselves. Your site won’t be unique, but it will look good quickly.
Luckily, it’s pretty easy to make Bootstrap not look too much like Bootstrap – using fonts, CSS effects, background images, colour schemes and so on. Most of the rest of this article covers different ways to achieve this.
We are going to customize this Bootstrap example page.
This already has some custom CSS in the . We’ll pull it all out, and create a new CSS file, custom.css. Then we add a reference to it in the header. Now we’re ready to start customizing things.
3. Fonts
Web fonts are one of the quickest ways to make your site look distinctive, modern, and less Bootstrappy, so we’ll start there.
First, we can add some sweet fonts, from Google Web Fonts. The intimidating bit is choosing fonts that look nice together. Luckily, there are plenty of suggestions around the web: we’re going to use one of DesignShack’s suggested free Google Fonts pairings. Our fonts are Corben (for headings) and Nobile (for body copy).
Then we add these files to our .
…and this to custom.css:
h1, h2, h3, h4, h5, h6 {
font-family: 'Corben', Georgia, Times, serif;
}
p, div {
font-family: 'Nobile', Helvetica, Arial, sans-serif;
}
Now our example looks like this. It’s not going to win any design awards, but it’s immediately better:
I also recommend the web font services Fontdeck, or Typekit – these have a wider selection of fonts, and are worth the investment if you regularly need to make sites look good. For more font combinations, Just My Type suggests appealing pairings from Typekit. Finally, you can experiment with type pairing ideas at Type Connection. For the design background on pairing fonts, Typekit’s post is worth a read.
4. Textures
An instant way to make a site look classy is to use textures. You know the grey, stripy, indefinably elegant background on 24ways.org? That.
If only there was a superb resource listing attractive, free, ready-to-use textures… Oh wait, there’s Atle Mo’s Subtle Patterns.
We’re going to use Cream Dust, for an effect that can only be described as subtle. We download the file to a new /img/ directory, then add this to the CSS file:
body {
background: url(/img/cream_dust.png) repeat 0 0;
}
Bang:
For some design background on patterns, I recommend reading through Smashing Magazine’s guidelines on textures. (TL;DR version: use textures to enhance beauty, and clarify the information architecture of your site; but don’t overdo it, or inadvertently obscure your text.)
Still more to do, though. Onwards.
5. Icons
Last year’s 24 ways taught us to use icon fonts for our site icons.
This is great for the time-pressed coder, because icon fonts don’t just cut down on HTTP requests – they’re a lot quicker to set up than image-based icons, too.
Bootstrap ships with an extensive, free for commercial use icon set in the shape of Font Awesome. Its icons are safe for screen readers, and can even be made to work in IE7 if needed (we’re not going to bother here).
To start using these icons, just download Font Awesome, and add the /fonts/ directory to your site and the font-awesome.css file into your /css/ directory. Then add a reference to the CSS file in your header:
Finally, we’ll add a truck icon to the main action button, as follows. Why a truck? Why not?
Sign up today
We’ll also tweak our CSS file to stop the icon nudging up against the button text:
.jumbotron .btn i {
margin-right: 8px;
}
And this is how it looks:
Not the most exciting change ever, but it livens up the page a bit. The licence is CC-BY-3.0, so we also include a mention of Font Awesome and its URL in the source code.
If you’d like something a little more distinctive, Shifticons lets you pay a few cents for individual icons, with the bonus that you only have to serve the icons you actually use, which is more efficient. Its icons are also friendly to screen readers, but won’t work in IE7.
6. CSS3
The next thing you could do is add some CSS3 goodness. It can really help the key elements of the site stand out.
If you are pressed for time, just adding box-shadow and text-shadow to emphasize headings and standouts can be useful:
h1 {
text-shadow: 1px 1px 1px #ccc;
}
.div-that-you want-to-stand-out {
box-shadow: 0 0 1em 1em #ccc;
}
We have a little more time though, so we’re going to do something more subtle. We’ll add a radial gradient behind the main heading, using an online gradient editor.
The output is hefty, but you can see it in the CSS. Note that we also need to add the following to our HTML, for IE9 support:
And the effect – I don’t know what a designer would think, but I like the way it makes the heading pop.
For a crash course in useful modern CSS effects, I highly recommend CodeSchool’s online course in Functional HTM5 and CSS3. It costs money ($25 a month to subscribe), but it’s worth it for the time you’ll save. As a bonus, you also get access to some excellent JavaScript, Ruby and GitHub courses.
(Incidentally, if you find yourself fighting with basic float and display attributes in CSS – and there’s no shame in it, CSS layout is not intuitive – I recommend the CSS Cross-Country course at CodeSchool.)
7. Add a twist
We could leave it there, but we’re going to add a background image, and give the site some personality.
This is the area of design that I think many programmers find most intimidating. How do we create the graphics and photographs that a designer would use? The answer is iStockPhoto and its competitors – online image libraries where you can find and pay for images. They won’t be unique, but for our purposes, that’s fine.
We’re going to use a Christmassy image. For a twist, we’re going to use Backstretch to make it responsive.
We must pay for the image, then download it to our /img/ directory. Then, we set it as our ’s background-image, by including a JavaScript file with just the following line:
$.backstretch(""/img/winter.jpg"");
We also reset the subtle pattern to become the background for our container image. It would look much better transparent, so we can use this technique in GIMP to make it see-through:
.container-narrow {
background: url(/img/cream_dust_transparent.png) repeat 0 0;
}
We also fiddle with the padding on body and .container-narrow a bit, and this is the result:
(Aside: If this were a real site, I’d want to buy images in multiple sizes and ensure that Backstretch chose the most appropriately sized image for our screen, perhaps using responsive images.)
How to find the effects that make a site interesting? I keep a set of bookmarks for interesting JavaScript and CSS effects I might want to use someday, from realistic shadows to animating grids. The JavaScript Weekly newsletter is a great source of ideas.
8. Colour schemes
We’re just about getting there – though we’re probably past half an hour now – but that button and that menu still both look awfully Bootstrappy.
Real sites, with real designers, have a colour palette, carefully chosen to harmonize and match the brand profile. For our purposes, we’re just going to borrow some colours from the image. We use Gimp’s colour picker tool to identify the hex values of the blue of the snow. Then we can use Color Scheme Designer to find contrasting, but complementary, colours.
Finally, we use those colours for our central button. There are lots of tools to help us do this, such as Bootstrap Buttons. The new HTML is quite long, so I won’t paste it all here, but you can find it in the CSS file.
We also reset the colour of the pills in the navigation menu, which is a bit easier:
.nav-pills > .active > a, .nav-pills > .active > a:hover {
background-color: #FF9473;
}
I’m not sure if the result is great to be honest, but at least we’ve lost those Bootstrap-blue buttons:
Another way to do it, if you didn’t have an image to match, would be to borrow an attractive colour scheme. Colourlovers is a community where people create and share ready-made colour palettes.
The key thing is to find a palette with an open licence, so you can legitimately use it. Unfortunately, you can’t search for palettes by licence type, but many do have open licences. Here’s a popular palette with a CC-BY-SA licence that allows reuse with attribution.
As above, you can use the hex values from the palette in your custom CSS, and bask in the newly colourful results.
9. Read on
With the above techniques, you can make a site that is starting to look slightly more professional, pretty quickly.
If you have the time to invest, it’s well worth learning some design principles, if only so that design seems less intimidating and more like fun. As part of my design learning, I read a few introductory design books aimed at coders. The best I found was David Kadavy’s Design for Hackers: Reverse-Engineering Beauty, which explains the basic principles behind choosing colours, fonts, typefaces and layout.
In the introduction to his book, David writes:
No group stands to gain more from design literacy than hackers do… The one subject that is exceedingly frustrating for hackers to try to learn is design. Hackers know that in order to compete against corporate behemoths with just a few lines of code, they need to have good, clear design, but the resources with which to learn design are simply hard to find.
Well said. If you have half a day to invest, rather than half an hour, I recommend getting hold of David’s book.
And the journey is over. Perhaps that took slightly more than half an hour, but with practice, using the above techniques can become second nature. What useful tools have I missed? Designers, how would you improve on the above? I would love to know, so please give me your views in the comments.",2012,Anna Powell-Smith,annapowellsmith,2012-12-16T00:00:00+00:00,https://24ways.org/2012/how-to-make-your-site-look-half-decent/,design
54,Putting My Patterns through Their Paces,"Over the last few years, the conversation around responsive design has shifted subtly, focusing not on designing pages, but on patterns: understanding the small, reusable elements that comprise a larger design system. And given that many of those patterns are themselves responsive, learning to manage these small layout systems has become a big part of my work.
The thing is, the more pattern-driven work I do, the more I realize my design process has changed in a number of subtle, important ways. I suppose you might even say that pattern-driven design has, in a few ways, redesigned me.
Meet the Teaser
Here’s a recent example. A few months ago, some friends and I redesigned The Toast. (It was a really, really fun project, and we learned a lot.) Each page of the site is, as you might guess, stitched together from a host of tiny, reusable patterns. Some of them, like the search form and footer, are fairly unique, and used once per page; others are used more liberally, and built for reuse. The most prevalent example of these more generic patterns is the teaser, which is classed as, uh, .teaser. (Look, I never said I was especially clever.)
In its simplest form, a teaser contains a headline, which links to an article:
Fairly straightforward, sure. But it’s just the foundation: from there, teasers can have a byline, a description, a thumbnail, and a comment count. In other words, we have a basic building block (.teaser) that contains a few discrete content types – some required, some not. In fact, very few of those pieces need to be present; to qualify as a teaser, all we really need is a link and a headline. But by adding more elements, we can build slight variations of our teaser, and make it much, much more versatile.
Nearly every element visible on this page is built out of our generic “teaser” pattern.
But the teaser variation I’d like to call out is the one that appears on The Toast’s homepage, on search results or on section fronts. In the main content area, each teaser in the list features larger images, as well as an interesting visual treatment: the byline and comment count were the most prominent elements within each teaser, appearing above the headline.
The approved visual design of our teaser, as it appears on lists on the homepage and the section fronts.
And this is, as it happens, the teaser variation that gave me pause. Back in the old days – you know, like six months ago – I probably would’ve marked this module up to match the design. In other words, I would’ve looked at the module’s visual hierarchy (metadata up top, headline and content below) and written the following HTML:
But then I caught myself, and realized this wasn’t the best approach.
Moving Beyond Layout
Since I’ve started working responsively, there’s a question I work into every step of my design process. Whether I’m working in Sketch, CSSing a thing, or researching a project, I try to constantly ask myself:
What if someone doesn’t browse the web like I do?
…Okay, that doesn’t seem especially fancy. (And maybe you came here for fancy.) But as straightforward as that question might seem, it’s been invaluable to so many aspects of my practice. If I’m working on a widescreen layout, that question helps me remember the constraints of the small screen; if I’m working on an interface that has some enhancements for touch, it helps me consider other input modes as I work. It’s also helpful as a reminder that many might not see the screen the same way I do, and that accessibility (in all its forms) should be a throughline for our work on the web.
And that last point, thankfully, was what caught me here. While having the byline and comment count at the top was a lovely visual treatment, it made for a terrible content hierarchy. For example, it’d be a little weird if the page was being read aloud in a speaking browser: the name of the author and the number of comments would be read aloud before the title of the article with which they’re associated.
That’s why I find it’s helpful to begin designing a pattern’s hierarchy before its layout: to move past the visual presentation in front of me, and focus on the underlying content I’m trying to support. In other words, if someone’s encountering my design without the CSS I’ve written, what should their experience be?
So I took a step back, and came up with a different approach:
Much, much better. This felt like a better match for the content I was designing: the headline – easily most important element – was at the top, followed by the author’s name and an excerpt. And while the comment count is visually the most prominent element in the teaser, I decided it was hierarchically the least critical: that’s why it’s at the very end of the excerpt, the last element within our teaser. And with some light styling, we’ve got a respectable-looking hierarchy in place:
Yeah, you’re right – it’s not our final design. But from this basic-looking foundation, we can layer on a bit more complexity. First, we’ll bolster the markup with an extra element around our title and byline:
With that in place, we can use flexbox to tweak our layout, like so:
.teaser-hed {
display: flex;
flex-direction: column-reverse;
}
flex-direction: column-reverse acts a bit like a change in gravity within our teaser-hed element, vertically swapping its two children.
Getting closer! But as great as flexbox is, it doesn’t do anything for elements outside our container, like our little comment count, which is, as you’ve probably noticed, still stranded at the very bottom of our teaser.
Flexbox is, as you might already know, wonderful! And while it enjoys incredibly broad support, there are enough implementations of old versions of Flexbox (in addition to plenty of bugs) that I tend to use a feature test to check if the browser’s using a sufficiently modern version of flexbox. Here’s the one we used:
var doc = document.body || document.documentElement;
var style = doc.style;
if ( style.webkitFlexWrap == '' ||
style.msFlexWrap == '' ||
style.flexWrap == '' ) {
doc.className += "" supports-flex"";
}
Eagle-eyed readers will note we could have used @supports feature queries to ask browsers if they support certain CSS properties, removing the JavaScript dependency. But since we wanted to serve the layout to IE we opted to write a little question in JavaScript, asking the browser if it supports flex-wrap, a property used elsewhere in the design. If the browser passes the test, then a class of supports-flex gets applied to our html element. And with that class in place, we can safely quarantine our flexbox-enabled layout from less-capable browsers, and finish our teaser’s design:
.supports-flex .teaser-hed {
display: flex;
flex-direction: column-reverse;
}
.supports-flex .teaser .comment-count {
position: absolute;
right: 0;
top: 1.1em;
}
If the supports-flex class is present, we can apply our flexbox layout to the title area, sure – but we can also safely use absolute positioning to pull our comment count out of its default position, and anchor it to the top right of our teaser. In other words, the browsers that don’t meet our threshold for our advanced styles are left with an attractive design that matches our HTML’s content hierarchy; but the ones that pass our test receive the finished, final design.
And with that, our teaser’s complete.
Diving Into Device-Agnostic Design
This is, admittedly, a pretty modest application of flexbox. (For some truly next-level work, I’d recommend Heydon Pickering’s “Flexbox Grid Finesse”, or anything Zoe Mickley Gillenwater publishes.) And for such a simple module, you might feel like this is, well, quite a bit of work. And you’d be right! In fact, it’s not one layout, but two: a lightly styled content hierarchy served to everyone, with the finished design served conditionally to the browsers that can successfully implement it. But I’ve found that thinking about my design as existing in broad experience tiers – in layers – is one of the best ways of designing for the modern web. And what’s more, it works not just for simple modules like our teaser, but for more complex or interactive patterns as well.
Open video
Even a simple search form can be conditionally enhanced, given a little layered thinking.
This more layered approach to interface design isn’t a new one, mind you: it’s been championed by everyone from Filament Group to the BBC. And with all the challenges we keep uncovering, a more device-agnostic approach is one of the best ways I’ve found to practice responsive design. As Trent Walton once wrote,
Like cars designed to perform in extreme heat or on icy roads, websites should be built to face the reality of the web’s inherent variability.
We have a weird job, working on the web. We’re designing for the latest mobile devices, sure, but we’re increasingly aware that our definition of “smartphone” is much too narrow. Browsers have started appearing on our wrists and in our cars’ dashboards, but much of the world’s mobile data flows over sub-3G networks. After all, the web’s evolution has never been charted along a straight line: it’s simultaneously getting slower and faster, with devices new and old coming online every day. With all the challenges in front of us, including many we don’t yet know about, a more device-agnostic, more layered design process can better prepare our patterns – and ourselves – for the future.
(It won’t help you get enough to eat at holiday parties, though.)",2015,Ethan Marcotte,ethanmarcotte,2015-12-10T00:00:00+00:00,https://24ways.org/2015/putting-my-patterns-through-their-paces/,code
104,Sitewide Search On A Shoe String,"One of the questions I got a lot when I was building web sites for smaller businesses was if I could create a search engine for their site. Visitors should be able to search only this site and find things without the maintainer having to put “related articles” or “featured content” links on every page by hand.
Back when this was all fields this wasn’t easy as you either had to write your own scraping tool, use ht://dig or a paid service from providers like Yahoo, Altavista or later on Google. In the former case you had to swallow the bitter pill of computing and indexing all your content and storing it in a database for quick access and in the latter it hurt your wallet.
Times have moved on and nowadays you can have the same functionality for free using Yahoo’s “Build your own search service” – BOSS. The cool thing about BOSS is that it allows for a massive amount of hits a day and you can mash up the returned data in any format you want. Another good feature of it is that it comes with JSON-P as an output format which makes it possible to use it without any server-side component!
Starting with a working HTML form
In order to add a search to your site, you start with a simple HTML form which you can use without JavaScript. Most search engines will allow you to filter results by domain. In this case we will search “bbc.co.uk”. If you use Yahoo as your standard search, this could be:
The Google equivalent is:
In any case make sure to use the ID term for the search term and site for the site, as this is what we are going to use for the script. To make things easier, also have an ID called customsearch on the form.
To use BOSS, you should get your own developer API for BOSS and replace the one in the demo code. There is click tracking on the search results to see how successful your app is, so you should make it your own.
Adding the BOSS magic
BOSS is a REST API, meaning you can use it in any HTTP request or in a browser by simply adding the right parameters to a URL. Say for example you want to search “bbc.co.uk” for “christmas” all you need to do is open the following URL:
http://boss.yahooapis.com/ysearch/web/v1/christmas?sites=bbc.co.uk&format=xml&appid=YOUR-APPLICATION-ID
Try it out and click it to see the results in XML. We don’t want XML though, which is why we get rid of the format=xml parameter which gives us the same information in JSON:
http://boss.yahooapis.com/ysearch/web/v1/christmas?sites=bbc.co.uk&appid=YOUR-APPLICATION-ID
JSON makes most sense when you can send the output to a function and immediately use it. For this to happen all you need is to add a callback parameter and the JSON will be wrapped in a function call. Say for example we want to call SITESEARCH.found() when the data was retrieved we can do it this way:
http://boss.yahooapis.com/ysearch/web/v1/christmas?sites=bbc.co.uk&callback=SITESEARCH.found&appid=YOUR-APPLICATION-ID
You can use this immediately in a script node if you want to. The following code would display the total amount of search results for the term christmas on bbc.co.uk as an alert:
However, for our example, we need to be a bit more clever with this.
Enhancing the search form
Here’s the script that enhances a search form to show results below it.
SITESEARCH = function(){
var config = {
IDs:{
searchForm:'customsearch',
term:'term',
site:'site'
},
loading:'Loading results...',
noresults:'No results found.',
appID:'YOUR-APP-ID',
results:20
};
var form;
var out;
function init(){
if(config.appID === 'YOUR-APP-ID'){
alert('Please get a real application ID!');
} else {
form = document.getElementById(config.IDs.searchForm);
if(form){
form.onsubmit = function(){
var site = document.getElementById(config.IDs.site).value;
var term = document.getElementById(config.IDs.term).value;
if(typeof site === 'string' && typeof term === 'string'){
if(typeof out !== 'undefined'){
out.parentNode.removeChild(out);
}
out = document.createElement('p');
out.appendChild(document.createTextNode(config.loading));
form.appendChild(out);
var APIurl = 'http://boss.yahooapis.com/ysearch/web/v1/' +
term + '?callback=SITESEARCH.found&sites=' +
site + '&count=' + config.results +
'&appid=' + config.appID;
var s = document.createElement('script');
s.setAttribute('src',APIurl);
s.setAttribute('type','text/javascript');
document.getElementsByTagName('head')[0].appendChild(s);
return false;
}
};
}
}
};
function found(o){
var list = document.createElement('ul');
var results = o.ysearchresponse.resultset_web;
if(results){
var item,link,description;
for(var i=0,j=results.length;i
Search this site:
Where to go from here
This is just a very simple example of what you can do with BOSS. You can define languages and regions, retrieve and display images and news and mix the results with other data sources before displaying them. One very cool feature is that by adding a view=keyterms parameter to the URL you can get the keywords of each of the results to drill deeper into the search. An example for this written in PHP is available on the YDN blog. For JavaScript solutions there is a handy wrapper called yboss available to help you go nuts.",2008,Christian Heilmann,chrisheilmann,2008-12-04T00:00:00+00:00,https://24ways.org/2008/sitewide-search-on-a-shoestring/,code
49,Universal React,"One of the libraries to receive a huge amount of focus in 2015 has been ReactJS, a library created by Facebook for building user interfaces and web applications.
More generally we’ve seen an even greater rise in the number of applications built primarily on the client side with most of the logic implemented in JavaScript. One of the main issues with building an app in this way is that you immediately forgo any customers who might browse with JavaScript turned off, and you can also miss out on any robots that might visit your site to crawl it (such as Google’s search bots). Additionally, we gain a performance improvement by being able to render from the server rather than having to wait for all the JavaScript to be loaded and executed.
The good news is that this problem has been recognised and it is possible to build a fully featured client-side application that can be rendered on the server. The way in which these apps work is as follows:
The user visits www.yoursite.com and the server executes your JavaScript to generate the HTML it needs to render the page.
In the background, the client-side JavaScript is executed and takes over the duty of rendering the page.
The next time a user clicks, rather than being sent to the server, the client-side app is in control.
If the user doesn’t have JavaScript enabled, each click on a link goes to the server and they get the server-rendered content again.
This means you can still provide a very quick and snappy experience for JavaScript users without having to abandon your non-JS users. We achieve this by writing JavaScript that can be executed on the server or on the client (you might have heard this referred to as isomorphic) and using a JavaScript framework that’s clever enough handle server- or client-side execution. Currently, ReactJS is leading the way here, although Ember and Angular are both working on solutions to this problem.
It’s worth noting that this tutorial assumes some familiarity with React in general, its syntax and concepts. If you’d like a refresher, the ReactJS docs are a good place to start.
Getting started
We’re going to create a tiny ReactJS application that will work on the server and the client. First we’ll need to create a new project and install some dependencies. In a new, blank directory, run:
npm init -y
npm install --save ejs express react react-router react-dom
That will create a new project and install our dependencies:
ejs is a templating engine that we’ll use to render our HTML on the server.
express is a small web framework we’ll run our server on.
react-router is a popular routing solution for React so our app can fully support and respect URLs.
react-dom is a small React library used for rendering React components.
We’re also going to write all our code in ECMAScript 6, and therefore need to install BabelJS and configure that too.
npm install --save-dev babel-cli babel-preset-es2015 babel-preset-react
Then, create a .babelrc file that contains the following:
{
""presets"": [""es2015"", ""react""]
}
What we’ve done here is install Babel’s command line interface (CLI) tool and configured it to transform our code from ECMAScript 6 (or ES2015) to ECMAScript 5, which is more widely supported. We’ll need the React transforms when we start writing JSX when working with React.
Creating a server
For now, our ExpressJS server is pretty straightforward. All we’ll do is render a view that says ‘Hello World’. Here’s our server code:
import express from 'express';
import http from 'http';
const app = express();
app.use(express.static('public'));
app.set('view engine', 'ejs');
app.get('*', (req, res) => {
res.render('index');
});
const server = http.createServer(app);
server.listen(3003);
server.on('listening', () => {
console.log('Listening on 3003');
});
Here we’re using ES6 modules, which I wrote about on 24 ways last year, if you’d like a reminder. We tell the app to render the index view on any GET request (that’s what app.get('*') means, the wildcard matches any route).
We now need to create the index view file, which Express expects to be defined in views/index.ejs:
My App
Hello World
Finally, we’re ready to run the server. Because we installed babel-cli earlier we have access to the babel-node executable, which will transform all your code before running it through node. Run this command:
./node_modules/.bin/babel-node server.js
And you should now be able to visit http://localhost:3003 and see ‘Hello World’ right there:
Building the React app
Now we’ll build the React application entirely on the server, before adding the client-side JavaScript right at the end. Our app will have two routes, / and /about which will both show a small amount of content. This will demonstrate how to use React Router on the server side to make sure our React app plays nicely with URLs.
Firstly, let’s update views/index.ejs. Our server will figure out what HTML it needs to render, and pass that into the view. We can pass a value into our view when we render it, and then use EJS syntax to tell it to output that data. Update the template file so the body looks like so:
<%- markup %>
Next, we’ll define the routes we want our app to have using React Router. For now we’ll just define the index route, and not worry about the /about route quite yet. We could define our routes in JSX, but I think for server-side rendering it’s clearer to define them as an object. Here’s what we’re starting with:
const routes = {
path: '',
component: AppComponent,
childRoutes: [
{
path: '/',
component: IndexComponent
}
]
}
These are just placed at the top of server.js, after the import statements. Later we’ll move these into a separate file, but for now they are fine where they are.
Notice how I define first that the AppComponent should be used at the '' path, which effectively means it matches every single route and becomes a container for all our other components. Then I give it a child route of /, which will match the IndexComponent. Before we hook these routes up with our server, let’s quickly define components/app.js and components/index.js. app.js looks like so:
import React from 'react';
export default class AppComponent extends React.Component {
render() {
return (
Welcome to my App
{ this.props.children }
);
}
}
When a React Router route has child components, they are given to us in the props under the children key, so we need to include them in the code we want to render for this component. The index.js component is pretty bland:
import React from 'react';
export default class IndexComponent extends React.Component {
render() {
return (
);
}
}
Server-side routing with React Router
Head back into server.js, and firstly we’ll need to add some new imports:
import React from 'react';
import { renderToString } from 'react-dom/server';
import { match, RoutingContext } from 'react-router';
import AppComponent from './components/app';
import IndexComponent from './components/index';
The ReactDOM package provides react-dom/server which includes a renderToString method that takes a React component and produces the HTML string output of the component. It’s this method that we’ll use to render the HTML from the server, generated by React. From the React Router package we use match, a function used to find a matching route for a URL; and RoutingContext, a React component provided by React Router that we’ll need to render. This wraps up our components and provides some functionality that ties React Router together with our app. Generally you don’t need to concern yourself about how this component works, so don’t worry too much.
Now for the good bit: we can update our app.get('*') route with the code that matches the URL against the React routes:
app.get('*', (req, res) => {
// routes is our object of React routes defined above
match({ routes, location: req.url }, (err, redirectLocation, props) => {
if (err) {
// something went badly wrong, so 500 with a message
res.status(500).send(err.message);
} else if (redirectLocation) {
// we matched a ReactRouter redirect, so redirect from the server
res.redirect(302, redirectLocation.pathname + redirectLocation.search);
} else if (props) {
// if we got props, that means we found a valid component to render
// for the given route
const markup = renderToString( );
// render `index.ejs`, but pass in the markup we want it to display
res.render('index', { markup })
} else {
// no route match, so 404. In a real app you might render a custom
// 404 view here
res.sendStatus(404);
}
});
});
We call match, giving it the routes object we defined earlier and req.url, which contains the URL of the request. It calls a callback function we give it, with err, redirectLocation and props as the arguments. The first two conditionals in the callback function just deal with an error occuring or a redirect (React Router has built in redirect support). The most interesting bit is the third conditional, else if (props). If we got given props and we’ve made it this far it means we found a matching component to render and we can use this code to render it:
...
} else if (props) {
// if we got props, that means we found a valid component to render
// for the given route
const markup = renderToString( );
// render `index.ejs`, but pass in the markup we want it to display
res.render('index', { markup })
} else {
...
}
The renderToString method from ReactDOM takes that RoutingContext component we mentioned earlier and renders it with the properties required. Again, you need not concern yourself with what this specific component does or what the props are. Most of this is data that React Router provides for us on top of our components.
Note the {...props}, which is a neat bit of JSX syntax that spreads out our object into key value properties. To see this better, note the two pieces of JSX code below, both of which are equivalent:
// OR:
const props = { a: ""foo"", b: ""bar"" };
Running the server again
I know that felt like a lot of work, but the good news is that once you’ve set this up you are free to focus on building your React components, safe in the knowledge that your server-side rendering is working. To check, restart the server and head to http://localhost:3003 once more. You should see it all working!
Refactoring and one more route
Before we move on to getting this code running on the client, let’s add one more route and do some tidying up. First, move our routes object out into routes.js:
import AppComponent from './components/app';
import IndexComponent from './components/index';
const routes = {
path: '',
component: AppComponent,
childRoutes: [
{
path: '/',
component: IndexComponent
}
]
}
export { routes };
And then update server.js. You can remove the two component imports and replace them with:
import { routes } from './routes';
Finally, let’s add one more route for ./about and links between them. Create components/about.js:
import React from 'react';
export default class AboutComponent extends React.Component {
render() {
return (
);
}
}
And then you can add it to routes.js too:
import AppComponent from './components/app';
import IndexComponent from './components/index';
import AboutComponent from './components/about';
const routes = {
path: '',
component: AppComponent,
childRoutes: [
{
path: '/',
component: IndexComponent
},
{
path: '/about',
component: AboutComponent
}
]
}
export { routes };
If you now restart the server and head to http://localhost:3003/about` you’ll see the about page!
For the finishing touch we’ll use the React Router link component to add some links between the pages. Edit components/app.js to look like so:
import React from 'react';
import { Link } from 'react-router';
export default class AppComponent extends React.Component {
render() {
return (
Welcome to my App
{ this.props.children }
);
}
}
You can now click between the pages to navigate. However, everytime we do so the requests hit the server. Now we’re going to make our final change, such that after the app has been rendered on the server once, it gets rendered and managed in the client, providing that snappy client-side app experience.
Client-side rendering
First, we’re going to make a small change to views/index.ejs. React doesn’t like rendering directly into the body and will give a warning when you do so. To prevent this we’ll wrap our app in a div:
<%- markup %>
I’ve also added in a script tag to build.js, which is the file we’ll generate containing all our client-side code.
Next, create client-render.js. This is going to be the only bit of JavaScript that’s exclusive to the client side. In it we need to pull in our routes and render them to the DOM.
import React from 'react';
import ReactDOM from 'react-dom';
import { Router } from 'react-router';
import { routes } from './routes';
import createBrowserHistory from 'history/lib/createBrowserHistory';
ReactDOM.render(
,
document.getElementById('app')
)
The first thing you might notice is the mention of createBrowserHistory. React Router is built on top of the history module, a module that listens to the browser’s address bar and parses the new location. It has many modes of operation: it can keep track using a hashbang, such as http://localhost/#!/about (this is the default), or you can tell it to use the HTML5 history API by calling createBrowserHistory, which is what we’ve done. This will keep the URLs nice and neat and make sure the client and the server are using the same URL structure. You can read more about React Router and histories in the React Router documentation.
Finally we use ReactDOM.render and give it the Router component, telling it about all our routes, and also tell ReactDOM where to render, the #app element.
Generating build.js
We’re actually almost there! The final thing we need to do is generate our client side bundle. For this we’re going to use webpack, a module bundler that can take our application, follow all the imports and generate one large bundle from them. We’ll install it and babel-loader, a webpack plugin for transforming code through Babel.
npm install --save-dev webpack babel-loader
To run webpack we just need to create a configuration file, called webpack.config.js. Create the file in the root of our application and add the following code:
var path = require('path');
module.exports = {
entry: path.join(process.cwd(), 'client-render.js'),
output: {
path: './public/',
filename: 'build.js'
},
module: {
loaders: [
{
test: /.js$/,
loader: 'babel'
}
]
}
}
Note first that this file can’t be written in ES6 as it doesn’t get transformed. The first thing we do is tell webpack the main entry point for our application, which is client-render.js. We use process.cwd() because webpack expects an exact location – if we just gave it the string ‘client-render.js’, webpack wouldn’t be able to find it.
Next, we tell webpack where to output our file, and here I’m telling it to place the file in public/build.js. Finally we tell webpack that every time it hits a file that ends in .js, it should use the babel-loader plugin to transform the code first.
Now we’re ready to generate the bundle!
./node_modules/.bin/webpack
This will take a fair few seconds to run (on my machine it’s about seven or eight), but once it has it will have created public/build.js, a client-side bundle of our application. If you restart your server once more you’ll see that we can now navigate around our application without hitting the server, because React on the client takes over. Perfect!
The first bundle that webpack generates is pretty slow, but if you run webpack -w it will go into watch mode, where it watches files for changes and regenerates the bundle. The key thing is that it only regenerates the small pieces of the bundle it needs, so while the first bundle is very slow, the rest are lightning fast. I recommend leaving webpack constantly running in watch mode when you’re developing.
Conclusions
First, if you’d like to look through this code yourself you can find it all on GitHub. Feel free to raise an issue there or tweet me if you have any problems or would like to ask further questions.
Next, I want to stress that you shouldn’t use this as an excuse to build all your apps in this way. Some of you might be wondering whether a static site like the one we built today is worth its complexity, and you’d be right. I used it as it’s an easy example to work with but in the future you should carefully consider your reasons for wanting to build a universal React application and make sure it’s a suitable infrastructure for you.
With that, all that’s left for me to do is wish you a very merry Christmas and best of luck with your React applications!",2015,Jack Franklin,jackfranklin,2015-12-05T00:00:00+00:00,https://24ways.org/2015/universal-react/,code
47,Developing Robust Deployment Procedures,"Once you have developed your site, how do you make it live on your web hosting? For many years the answer was to log on to your server and upload the files via FTP. Over time most hosts and FTP clients began to support SFTP, ensuring your files were transmitted over a secure connection. The process of deploying a site however remained the same.
There are issues with deploying a site in this way. You are essentially transferring files one by one to the server without any real management of that transfer. If the transfer fails for some reason, you may end up with a site that is only half updated. It can then be really difficult to work out what hasn’t been replaced or added, especially where you are updating an existing site. If you are updating some third-party software your update may include files that should be removed, but that may not be obvious to you and you risk leaving outdated files littering your file system. Updating using (S)FTP is a fragile process that leaves you open to problems caused by both connectivity and human error. Is there a better way to do this?
You’ll be glad to know that there is. A modern professional deployment workflow should have you moving away from fragile manual file transfers to deployments linked to code committed into source control.
The benefits of good practice
You may never have experienced any major issues while uploading files over FTP, and good FTP clients can help. However, there are other benefits to moving to modern deployment practices.
No surprises when you launch
If you are deploying in the way I suggest in this article you should have no surprises when you launch because the code you committed from your local environment should be the same code you deploy – and to staging if you have a staging server. A missing vital file won’t cause things to start throwing errors on updating the live site.
Being able to work collaboratively
Source control and good deployment practice makes working with your clients and other developers easy. Deploying first to a staging server means you can show your client updates and then push them live. If you subcontract some part of the work, you can give your subcontractor the ability to deploy to staging, leaving you with the final push to launch, once you know you are happy with the work.
Having a proper backup of site files with access to them from anywhere
The process I will outline requires the use of hosted, external source control. This gives you a backup of your latest commit and the ability to clone those files and start working on them from any machine, wherever you are.
Being able to jump back into a site quickly when the client wants a few changes
When doing client work it is common for some work to be handed over, then several months might go by without you needing to update the site. If you don’t have a good process in place, just getting back to work on it may take several hours for what could be only a few hours of work in itself. A solid method for getting your local copy up to date and deploying your changes live can cut that set-up time down to a few minutes.
The tool chain
In the rest of this article I assume that your current practice is to deploy your files over (S)FTP, using an FTP client. You would like to move to a more robust method of deployment, but without blowing apart your workflow and spending all Christmas trying to put it back together again. Therefore I’m selecting the most straightforward tools to get you from A to B.
Source control
Perhaps you already use some kind of source control for your sites. Today that is likely to be Git but you might also use Subversion or Mercurial. If you are not using any source control at all then I would suggest you choose Git, and that is what I will be working with in this article.
When you work with Git, you always have a local repository. This is where your changes are committed. You also have the option to push those changes to a remote repository; for example, GitHub. You may well have come across GitHub as somewhere you can go to download open source code. However, you can also set up private repositories for sites whose code you don’t want to make publicly accessible.
A hosted Git repository gives you somewhere to push your commits to and deploy from, so it’s a crucial part of our tool chain.
A deployment service
Once you have your files pushed to a remote repository, you then need a way to deploy them to your staging environment and live server. This is the job of a deployment service.
This service will connect securely to your hosting, and either automatically (or on the click of a button) transfer files from your Git commit to the hosting server. If files need removing, the service should also do this too, so you can be absolutely sure that your various environments are the same.
Tools to choose from
What follows are not exhaustive lists, but any of these should allow you to deploy your sites without FTP.
Hosted Git repositories
GitHub
Beanstalk
Bitbucket
Standalone deployment tools
Deploy
dploy.io
FTPloy
I’ve listed Beanstalk as a hosted Git repository, though it also includes a bundled deployment tool. Dploy.io is a standalone version of that tool just for deployment. In this tutorial I have chosen two separate services to show how everything fits together, and because you may already be using source control. If you are setting up all of this for the first time then using Beanstalk saves having two accounts – and I can personally recommend them.
Putting it all together
The steps we are going to work through are:
Getting your local site into a local Git repository
Pushing the files to a hosted repository
Connecting a deployment tool to your web hosting
Setting up a deployment
Get your local site into a local Git repository
Download and install Git for your operating system.
Open up a Terminal window and tell Git your name using the following command (use the name you will set up on your hosted repository).
> git config --global user.name ""YOUR NAME""
Use the next command to give Git your email address. This should be the address that you will use to sign up for your remote repository.
> git config --global user.email ""YOUR EMAIL ADDRESS""
Staying in the command line, change to the directory where you keep your site files. If your files are in /Users/rachel/Sites/mynicewebite you would type:
> cd /Users/rachel/Sites/mynicewebsite
The next command tells Git that we want to create a new Git repository here.
> git init
We then add our files:
> git add .
Then commit the files:
> git commit -m “Adding initial files”
The bit in quotes after -m is a message describing what you are doing with this commit. It’s important to add something useful here to remind yourself later why you made the changes included in the commit.
Your local files are now in a Git repository! However, everything should be just the same as before in terms of working on the files or viewing them in a local web server. The only difference is that you can add and commit changes to this local repository.
Want to know more about Git? There are some excellent resources in a range of formats here.
Setting up a hosted Git repository
I’m going to use Atlassian Bitbucket for my first example as they offer a free hosted and private repository.
Create an account on Bitbucket. Then create a new empty repository and give it a name that will identify the repository easily.
Click Getting Started and under Command Line select “I have an existing project”. This will give you a set of instructions to run on the command line. The first instruction is just to change into your working directory as we did before. We then add a remote repository, and run two commands to push everything up to Bitbucket.
cd /path/to/my/repo
git remote add origin https://myuser@bitbucket.org/myname/24ways-tutorial.git
git push -u origin --all
git push -u origin --tags
When you run the push command you will be asked for the password that you set for Bitbucket. Having entered that, you should be able to view the files of your site on Bitbucket by selecting the navigation option Source in the sidebar.
You will also be able to see commits. When we initially committed our files locally we added the message “Adding initial files”. If you select Commits from the sidebar you’ll see we have one commit, with the message we set locally. You can imagine how useful this becomes when you can look back and see why you made certain changes to a project that perhaps you haven’t worked on for six months.
Before working on your site locally you should run:
> git pull
in your working directory to make sure you have all of the most up-to-date files. This is especially important if someone else might work on them, or you just use multiple machines.
You then make your changes and add any changed or modified files, for example:
> git add index.php
Commit the change locally:
> git commit -m “updated the homepage”
Then push it to Bitbucket:
> git push origin master
If you want to work on your files on a different computer you clone them using the following command:
> git clone https://myuser@bitbucket.org/myname/24ways-tutorial.git
You then have a copy of your files that is already a Git repository with the Bitbucket repository set up as a remote, so you are all ready to start work.
Connecting a deployment tool to your repository and web hosting
The next step is deploying files. I have chosen to use a deployment tool called Deploy as it has support for Bitbucket. It does have a monthly charge – but offers a free account for open source projects.
Sign up for your account then log in and create your first project. Select Create an empty project. Under Configure Repository Details choose Bitbucket and enter your username and password.
If Deploy can connect, it will show you your list of projects. Select the one you want.
The next screen is Add New Server and here you need to configure the server that you want to deploy to. You might set up more than one server per project. In an ideal world you would deploy to a staging server for your client preview changes and then deploy once everything is signed off. For now I’ll assume you just want to set up your live site.
Give the server a name; I usually use Production for the live web server. Then choose the protocol to connect with. Unless your host really does not support SFTP (which is pretty rare) I would choose that instead of FTP.
You now add the same details your host gave you to log in with your SFTP client, including the username and password. The Path on server should be where your files are on the server. When you log in with an SFTP client and you get put in the directory above public_html then you should just be able to add public_html here.
Once your server is configured you can deploy. Click Deploy now and choose the server you just set up. Then choose the last commit (which will probably be selected for you) and click Preview deployment. You will then get a preview of which files will change if you run the deployment: the files that will be added and any that will be removed. At the very top of that screen you should see the commit message you entered right back when you initially committed your files locally.
If all looks good, run the deployment.
You have taken the first steps to a more consistent and robust way of deploying your websites. It might seem like quite a few steps at first, but you will very soon come to realise how much easier deploying a live site is through this process.
Your new procedure step by step
Edit your files locally as before, testing them through a web server on your own computer.
Commit your changes to your local Git repository.
Push changes to the remote repository.
Log into the deployment service.
Hit the Deploy now button.
Preview the changes.
Run the deployment and then check your live site.
Taking it further
I have tried to keep things simple in this article because so often, once you start to improve processes, it is easy to get bogged down in all the possible complexities. If you move from deploying with an FTP client to working in the way I have outlined above, you’ve taken a great step forward in creating more robust processes. You can continue to improve your procedures from this point.
Staging servers for client preview
When we added our server we could have added an additional server to use as a staging server for clients to preview their site on. This is a great use of a cheap VPS server, for example. You can set each client up with a subdomain – clientname.yourcompany.com – and this becomes the place where they can view changes before you deploy them.
In that case you might deploy to the staging server, let the client check it out and then go back and deploy the same commit to the live server.
Using Git branches
As you become more familiar with using Git, and especially if you start working with other people, you might need to start developing using branches. You can then have a staging branch that deploys to staging and a production branch that is always a snapshot of what has been pushed to production. This guide from Beanstalk explains how this works.
Automatic deployment to staging
I wouldn’t suggest doing automatic deployment to the live site. It’s worth having someone on hand hitting the button and checking that everything worked nicely. If you have configured a staging server, however, you can set it up to deploy the changes each time a commit is pushed to it.
If you use Bitbucket and Deploy you would create a deployment hook on Bitbucket to post to a URL on Deploy when a push happens to deploy the code. This can save you a few steps when you are just testing out changes. Even if you have made lots of changes to the staging deployment, the commit that you push live will include them all, so you can do that manually once you are happy with how things look in staging.
Further Reading
The tutorials from Git Client Tower, already mentioned in this article, are a great place to start if you are new to Git.
A presentation from Liam Dempsey showing how to use the GitHub App to connect to Bitbucket
Try Git from Code School
The Git Workbook a self study guide to Git from Lorna Mitchell
Get set up for the new year
I love to start the New Year with a clean slate and improved processes. If you are still wrangling files with FTP then this is one thing you could tick off your list to save you time and energy in 2015. Post to the comments if you have suggestions of tools or ideas for ways to enhance this type of set-up for those who have already taken the first steps.",2014,Rachel Andrew,rachelandrew,2014-12-04T00:00:00+00:00,https://24ways.org/2014/developing-robust-deployment-procedures/,process
285,"Composing the New Canon: Music, Harmony, Proportion","Ohne Musik wäre das Leben ein Irrtum
—Friedrich NIETZSCHE, Götzen-Dämmerung, Sprüche und Pfeile 33, 1889
Somehow, music is hardcoded in human beings. It is something we understand and respond to without prior knowledge. Music exercises the emotions and our imaginative reflex, not just our hearing. It behaves so much like our emotions that music can seem to symbolize them, to bear them from one person to another. Not surprisingly, it conjures memories: the word music derives from Greek μουσική (mousike), art of the Muses, whose mythological mother was Mnemosyne, memory. But it can also summon up the blood, console the bereaved, inspire fanaticism, bolster governments and dissenters alike, help us learn, and make web designers dance. And what would Christmas be without music?
Music moves us, often in ways we can’t explain. By some kind of alchemy, music frees us from the elaborate nuisance and inadequacy of words. Across the world and throughout recorded history – and no doubt well before that – people have listened and made (and made out to) music.
[I]t appears probable that the progenitors of man, either the males or females or both sexes, before acquiring the power of expressing their mutual love in articulate language, endeavoured to charm each other with musical notes and rhythm.
—Charles DARWIN, The Descent of Man, and Selection in Relation to Sex, 1871
It’s so integral to humankind, we’ve sent it into space as a totem for who we are. (Who knows? It might be important.) Music is essential, a universal compulsion; as Nietzsche wrote, without music life would be a mistake.
Music, design and web design
There are some obvious and notable similarities between music and visual design. Both can convey mood and evoke emotion but, even under close scrutiny, how they do that remains to a great extent mysterious. Each has formal qualities or parts that can be abstracted, analysed and discussed, often using the same terminology: composition, harmony, rhythm, repetition, form, theme; even colour, texture and tone.
A possible reason for these shared aspects is that both visual design and music are means to connect with people in deep and lasting ways. Furthermore, I believe the connections to be made can complement direct emotional appeal. Certain aesthetic qualities in music work on an unconscious and, it could be argued, universal level. Using musical principles in our designs, then, can help provide the connectedness between content, device and user that we now seek as web designers.
Yet, when we talk about music and web design, the conversation is almost always about the music designers listen to while working, a theme finding its apotheosis in Designers.MX. Sometimes, articles in that dreary list format seek inspiration from music industry websites. There’s even a service offering pre-templated web designs for bands, and at least one book surveyed the landscape back in 2006. Occasionally, discussions broaden somewhat into whether and how different kinds of music can inspire and influence the design work we produce.
Such enquiries, it seems to me, are beside the point. Do I really design differently when I listen to Bach rather than Bacharach? Will the barely restrained energy of Count Basie’s The Kid from Red Bank mean I choose a lively colour palette, and rural, autumnal shades when inspired by Fleet Foxes? Mahler means a thirteen-column layout? Gillian Welch leads to distressed black and white photography? While reflecting the importance we place in music and how it seems to help us in our work, surveys on musical taste and lists of favourite artists fail to recognize that some of the fundamental aesthetic characteristics of music can be adapted and incorporated into modern web design.
Antiphonal geometry
Over recent years, web designers have embraced grid systems as powerful tools to help create good-looking and intuitive user experiences. With the advent of responsive design, these grids and their contents must adapt to the different screen sizes and properties of all kinds of user devices. Finding and using grid values that can scale well and retain or enhance their proportions and relationships while making the user experience meaningful in several different contexts is more important than ever.
In print, this challenge has always started with the dimensions and proportions of the page. Content can thereby be made to belong inside the page and be bound to it. And music has been used for centuries to further this aim. As Robert Bringhurst says in The Elements of Typographical Style:
Indeed, one of the simplest of all systems of page proportions is based on the familiar intervals of the diatonic scale. Pages that embody these basic musical proportions have been in common use in Europe for more than a thousand years.
Very well. But while he goes on to list (from the full chromatic scale, rather than just diatonic) the proportions and the musical intervals they’re based on, Bringhurst fails to mention what they’re ratios of or their potential effects. Shame. In his favour, however, he later touches on how proportions in print might be considered to work:
The page is a piece of paper. It is also a visible and tangible proportion, silently sounding the thoroughbass of the book. On it lies the textblock, which must answer to the page. The two together – page and textblock – produce an antiphonal geometry. That geometry alone can bond the reader to the book. Or conversely, it can put the reader to sleep, or put the reader’s nerves on edge, or drive the reader away.
So what does Bringhurst mean by antiphonal geometry, a phrase that marries the musical to the spatial? By stating that the textblock “must answer to the page”, the implication is that the relationship between the proportions of the page and the shape of the textblock printed on it embodies a spatial (geometrical) call-and-response (antiphony) that can be appealing or not.
Boulton’s new canon
But, as Mark Boulton has pointed out, on the web “there are no edges. There are no ‘pages’. We’ve made them up.” So, what is to be done? In January 2011 at the New Adventures in Web Design conference, Boulton presented his vision of a new canon of web design, a set of principles to guide us as we design the web. There are three overlapping tenets:
design from the content out
create connectedness between the different content elements
bind the content to the web device
Rather than design from the edges in, we need to design layout systems from the content out. To this end, Boulton asserts that grid system design should begin with a constraint, and he suggests we use the size of a fixed content element, such as an advertising unit or image, as a starting point for online grid calculations. Khoi Vinh advocates the same approach in his book, Ordering Disorder: Grid Principles for Web Design.
Boulton’s second and third tenets, however, are more complex and overlap significantly with each other. Connecting the different parts of the content and binding the content to the device share many characteristics and solutions:
adopting ems and percentages as units of size for layout elements
altering text size, line length and line height for different viewport dimensions
providing higher resolution images for devices with greater pixel densities
fluid layout grids, flexible images and responsive design
All can help relate the presentation of the content to its delivery in a certain context.
But how do we determine the relationship between one element of a layout and another? How can we avoid making arbitrary decisions about the relative sizes of parts of our designs? What can we use to connect the parts of our design to one another, and how can we bind the presentation of the content to the user’s device?
Tim Brown’s application of modular typographic scales hints at an answer. In the very useful tool he created for calculating such scales, Brown includes two musical ratios: the perfect fifth (2:3); and the perfect fourth (3:4). Why? Where do they come from? And what do they mean?
Harmonies musical and visual
Fundamental to music are rhythm and harmony.
As any drummer will tell you, without rhythm there is no music. Even when there’s no regular beat, any tune follows a rhythm, however irregular, simply because a change of note is a point of change in the music. Although rhythm, timing and pacing are all relevant to interaction design, right now it’s harmony we’re interested in.
Sometimes harmony is called the vertical aspect of music, and melody the horizontal. But this conceit overlooks the fact that harmony is both vertical and horizontal. A single melodic line, as it is played, implies various sets of harmonies on which it is grounded, whether or not those harmonies are played. So, harmony doesn’t just sit vertically beneath the horizontal melody, but moves horizontally as well, through harmonic progression.
To stretch this arrangement pixel-thin, we could argue that in onscreen design melody is the content, and the layout and arrangement of the content is the harmony. We sometimes say a design is harmonious when the interplay of different elements of a design is pleasing or balanced or in proportion, and the content (the melody) is set off or conveyed well by or appropriate to the design.
We seem to know instinctively whether a layout is harmonious…
In the design of The Great Discontent, the relationships between different elements combine to form a balanced whole.
…or not.
There’s no harmony in the Department for Education’s website because the different parts of the content don’t feel related to one another.
What is it that makes one design harmonious and another dissonant? It’s not just whether things line up, though that’s a start. I believe there are much deeper aesthetic forces at work, forces we can tap into in our onscreen designs. Now, I’m not going start a difficult discussion about aesthetics. For our purposes, we just need to know that it’s the branch of philosophy dealing with the nature of beauty, and the creation and perception of beauty. And among the key components in the perception of beauty are harmony and proportion. These have been part of traditional western aesthetics since Plato (about 2,500 years).
One of the ways we appreciate the beauty of music is through the harmonic intervals we hear. A musical interval is a combination of two notes and it describes the distance between the two pitches. For example, the distance between C and the G above it (if we take C as the tonic or root) is called a perfect fifth.
Left: C to G, a perfect fifth. Right: C and G, not a perfect fifth.
And, to get superficially scientific for a moment, each musical interval can be expressed as a ratio of the wavelength frequencies of the notes; for our perfect fifth, with every two wavelengths of C, there are three of G. And what is a ratio, if not a proportion of one thing to another?
So, simple musical harmony (using what’s known as just intonation1) affords us a set of proportions, expressed as ratios. Where better to apply these ideas of harmony and proportion from music in web design, than grid systems?
A digression: whither φ?
Quite often in our discussions of pure design and aesthetics, we mention the golden ratio and regurgitate the same justifications for its use: roots in antiquity; embodied in classical and Renaissance architecture and art; occurrence in nature; the New Twitter, and so forth (oh, really?).
Yet the ratios of musical intervals from just intonation are equally venerable and much more widespread: described by Pythagorus; employed in Palladian architecture, and printing, books and art from the Renaissance onwards; in modern times, film and television dimensions; standard international paper sizes (ISO 216, the A and B series); and, again and again, screen dimensions – chances are that screen you’re probably looking at right now has the proportions 2:3 (iPhone and iPod Touch), 3:4 (iPad and Kindle), 3:5 (many smartphones), 5:8 or 16:9 (many widescreen monitors), all ratios of musical intervals.
Back to our theme…
Musical interval ratios
Let’s take a look at most of the ratios within a couple of octaves and crunch some numbers to generate some percentages and other values that we can use in our designs. First, the intervals and their ratios in just intonation and expressed as ratios of one:
Name
Interval in C
Ratio
Ratio (1:x)
unison
C→C
1:1
1:1
minor second
C→D♭
15:16
1:1.067
major second
C→D
8:9
1:1.125
minor third
C→E♭
5:6
1:1.2
major third
C→E
4:5
1:1.25
perfect fourth
C→F
3:4
1:1.333
augmented fourth
or diminished fifth
C→F♯/G♭
1:√2
1:1.414
perfect fifth
C→G
2:3
1:1.5
minor sixth
C→A♭
5:8
1:1.6
major sixth
C→A
3:5
1:1.667
minor seventh
C→B♭
9:16
1:1.778
major seventh
C→B
8:15
1:1.875
octave
C→C↑
1:2
1:2
major tenth
C→E↑
2:5
1:2.5
major eleventh
C→F↑
3:8
1:2.667
major twelfth
C→G↑
1:3
1:3
double octave
C→C↑
1:4
1:4
Name
Interval in C
Ratio
Ratio (1:x)
And now as percentages, of both the larger and smaller values in the ratios:
Name
Ratio
% of larger value
% of smaller value
unison
1:1
100%
100%
minor second
15:16
93.75%
106.667%
major second
8:9
88.889%
112.5%
minor third
5:6
83.333%
120%
major third
4:5
80%
125%
perfect fourth
3:4
75%
133.333%
augmented fourth
or diminished fifth
1:√2
70.711%
141.421%
perfect fifth
2:3
66.667%
150%
minor sixth
5:8
62.5%
160%
major sixth
3:5
60%
166.667%
minor seventh
9:16
56.25%
177.778%
major seventh
8:15
53.333%
187.5%
octave
1:2
50%
200%
major tenth
2:5
40%
250%
major eleventh
3:8
37.5%
266.667%
major twelfth
1:3
33.333%
300%
double octave
1:4
25%
400%
Name
Ratio
% of larger value
% of smaller value
As you can see, the simple musical intervals are expressed as ratios of small whole numbers (integers). We can then normalize them as ratios of one, as well as derive percentage values, both in terms of the smaller value to the larger, and vice versa. These are the numbers we can incorporate into our designs. If you’ve ever written something like body { font: 100%/1.5 ""Museo Sans"", Helvetica, sans-serif; } in your CSS, you’re already using a musical ratio: the perfect fifth.
Modular scales allow us to generate a set of numbers based on a musical interval that can be used for all kinds of typographic and layout decisions to create harmony in a visual design for the web. As Tim Brown said at the 2010 Build conference:
I think that from that most atomic unit – type – whole experiences can resonate, whole experiences can be harmonious. And whole experiences can have a purpose suited to our design intentions.
Once more, with feeling: connectedness
As well as modular scales, there are other methods of incorporating musical interval ratios into our work. Setting the ratio of font size to line height in CSS is one such example. We could also create a typographic hierarchy using the same principle and combining several ratios that we know harmonize well musically in a chord:
body { font-size: 75%; } /* =12px = base size or tonic */
h1 { font-size: 32px; font-size: 2.667rem; }
/* =32px = 3:8 = major eleventh (C→F↑) */
h2 { font-size: 24px; font-size: 2rem; }
/* =24px = 1:2 = octave (C→C↑) */
h3 { font-size: 20px; font-size: 1.667rem; }
/* =20px = 3:5 = major sixth (C→A) */
figcaption, small { font-size: 9px; font-size : 0.75rem }
/* =9px = 3:4 = perfect fourth (C→F) */
Whoa! Hold your reindeer, Santa! How can we know what interval combinations work well together to form chords? Well, I’m a classically trained musician, so perhaps I have an advantage. To avoid a long, technically complex digression into musical harmony, here are a few basic combinations of intervals that are harmonious in one way or another:
unison; major third; perfect fifth; octave
unison; perfect fourth; major sixth; octave
unison; minor third; minor sixth; octave
unison; minor third; diminished fifth; major sixth; octave
This isn’t to say that other combinations can’t be used to interesting effect and particular purpose – they surely can – but I have to make sure there’s something left for you to experiment with in the wee small hours over the holiday. Bear in mind, though, were I to play you two notes from the same scale to form a minor second, for example, you’d probably say it was dissonant and maybe that quality of the 15:16 ratio would be translated to the design.
In the typographic hierarchy above, you’ll notice I used an interval in the higher octave, which affords a broader range of ratios while retaining the harmony. Thus, a perfect fifth (2:3) becomes a major twelfth (1:3), or a major sixth (3:5) becomes a major thirteenth (3:10).
The harmonic ratios can obviously be used as proportions for layout as well, in several different ways:
image width and height (for example, 450×800px = 9:16 = minor seventh)
main content to page width (67%:100% = 2:3 = perfect fifth)
page width to viewport width (80%:100% = 4:5 = major third)
One great benefit of using such ratios in web design work is that they can be applied in responsive web design. Proportional values, based on percentages or equivalent em units, will scale with changing viewports, so your layout and image proportions can be maintained or deliberately changed, as we’re about to find out, across devices.
Small speakers, tall speakers: binding to the device
The musical interval ratios also provide an opportunity, not only to create connectedness between the parts of a layout, but to bind the content to a device – that elusive antiphonal geometry. Just as a textblock and page resonate together, so too can web content and the screen. Earlier, I mentioned that several common screen aspect ratios match musical interval ratios. It would seem, then, that we have a set of proportions that we can use in different ways to establish and retain a sense of harmony that can be based on and change with those contexts. Using musical interval ratios, we can bind the display of our content to the device it’s displayed on.
If you haven’t met already, let me introduce you to the device-aspect-ratio property of CSS media queries.
@media only screen and (device-aspect-ratio: 3/4) { }
@media only screen and (device-aspect-ratio: 480/640) { }
@media only screen and (device-aspect-ratio: 600/800) { }
@media only screen and (device-aspect-ratio: 768/1024) { }
Regardless of the precise pixel values, each of these media queries would apply to devices whose display area has an aspect ratio of 3:4. It works by comparing the device-width with the device-height. (It’s not to be confused with aspect-ratio, which is defined by the width and height of the browser within the device.) The values in the media query are always presented as width/height, with portrait being the default orientation for smartphones and tablets; that is, to match an iPhone screen, you’d use device-aspect-ratio: 2/3, not 3/2, which won’t work.
Here’s a table of the musical intervals with their corresponding screens.
Name
device-aspect-ratio
Screens
Common resolutions (pixels)
major third
5/4
TFT LCD computer screens
1,280×1,024
perfect fourth
3/4 or 4/3
iPad, Kindle and other tablets, PDAs
320×240, 768×1,024
perfect fifth
2/3
iPhone, iPod Touch
320×480, 640×960
minor sixth
8/5 (16/10)
Many widescreens
1,152×720, 1,440×900, 1,920×1,200
major sixth
3/5
Many smartphones
240×400, 480×800
minor seventh
16/9 or 9/16
Many widescreens and some smartphones
720×1,280, 1,366×768, 1,920×1,080, 2,560×1,440
[You might argue that I’m playing fast and loose with the ratios. I suppose, mathematically speaking, 9:16 is not the same as 16:9: I’m no expert. But let’s not throw the baby out with the bath water, particularly at Christmas.]
With this in mind, we can begin to write media queries that will influence various typographic and layout values in line with the aspect ratios of specific screens and in combination with em-based min-width queries that work from smaller, mobile screens to larger, desktop screens.
Here’s a very simple demo page with only some text, an image with a caption and a little basic layout: no seasonal overindulgence here.
Demo: Sample page using device-aspect-ratio media queries based on musical interval ratios
Our initial styles for all devices are based on the perfect fifth, with the major third and octave rounding things out into a harmonious whole, whether or not media queries are supported. For example:
html { font-size: 100%; line-height: 1.5; }
/* font-size:line-height = 16:24 = 2:3 = perfect fifth */
h1 { font-size: 32px; font-size: 2rem; line-height: 1.25; }
/* font-size:line-height = 32:40 = 4:5 = major third
body:h1 = 16:32 = 1:2 = octave */
While we should really consider methods of delivering images appropriate to the screen size, let’s just stick to a single image for all devices. But why don’t we change its aspect ratio from 4:3 to 3:2, to fit with our harmonic scheme? It’s easy enough to do with overflow:hidden on the element to hide a part of the image, and a negative margin fudge:
figure img { margin: -8.5% 0 0 0; width: 100%; max-width: 100%; }
Our first break point targets devices 320 pixels wide with an aspect ratio of 2:3, namely the iPhone and iPod Touch:
/* 320px = 20×16 */
@media only screen and (min-width: 20em) and (device-aspect-ratio: 2/3) { }
We’re actually already there, of course, as the intervals we’ve chosen resonate with this aspect ratio – the content is already bound to the device.
Our next media query, then, will make some changes to match a different ratio, the major sixth (3:5), which is same as that of many smartphones:
/* 480px = 30×16 */
@media only screen and (min-width: 30em) and (device-aspect-ratio: 3/5) { }
A different aspect ratio might require a change in harmony. For devices with these proportions, we’ll now use the perfect fourth (3:4) and the major sixth (3:5) along with the octave we already have to create a new resonating harmony. For instance, a slightly wider screen means we can increase the line-height to aid the legibility of longer lines:
html { line-height: 1.667; }
/* font-size:line-height = 16:26.672 = 3:5 = major sixth */
h1 { font-size: 32px; font-size: 2rem; line-height: 1.667; }
/* font-size:line-height = 32:53.333 = 3:5 = major sixth
body:h1 = 16:32 = 1:2 = octave */
and we can remove the negative margin to display our 4:3 image in its entirety.
Each screen displays content styled using relationships related to its own proportions. On the left, an iPhone 4 (2:3); on the right, a Samsung Nexus S (3:5). Your mileage may vary.
Another device, another media query. At 768 pixels, screens are wide enough to add columns. The ratios we’ve used for the 3:5 screens include the perfect fourth (3:4) so we don’t need to change any of the font measurements, but we can base the proportions of the columns on the major sixth interval:
article { float: left; width: 56%; }
/* width of main column 3:5 (60% of 100%, major sixth)
incorporating gutter width */
aside { float : right; width : 36%; }
On devices with a 3:4 aspect ratio, this works even better in landscape orientation.
While not every screen over 768 pixels wide will have 3:4 proportions, the range of intervals informing the design ensure harmonious relationships between the different parts of the layout.
For wide screens proper (break point at 1,280 pixels) we can employ a new set of harmonious intervals. Many laptop and desktop screens have a 16:10 aspect ratio, which boils down to 8:5, equivalent to the minor sixth (5:8). Combined with a minor third (5:6) and the octave (1:2), this creates a new harmony appropriate to these devices. Let’s increase the font size and change the image’s aspect ratio to match:
html { font-size: 120%; line-height: 1.6; }
/* font-size increased for wider screens from 16px to 19.2px
(5:6 = minor third)
font-size:line-height = 19.2:30.72 = 5:8 = minor sixth */
figure img { margin: -12.5% 0 0 ; }
/* using -ve margin combined with overflow:hidden
on the figure element
to crop the image from 4:3 to 8:5 = minor sixth */
A wide screen with a 8:5 (16:10) aspect ratio and an image to match.
With more pixels at our disposal, we can also now use the musical interval ratios to determine the width of the layout, and change the column proportions as well:
section { margin: 0 auto; width: 83.333%; }
/* content width:screen width = 5:6 = minor third */
article { width: 60%; }
/* width of main column 5:8 (62.5% of 100%, minor sixth)
incorporating gutter width */
aside { width: 35%; }
With some carefully targeted media queries, we can begin to reach towards fulfilling the second and third tenets of Boulton’s new canon for web design: connecting the parts of content through relationships embodied in the layout design; and binding the content to the devices people use to access it.
Coda
Musical interval ratios and screen aspect ratios reveal more than convenient correspondence. These proportions work on a deep aesthetic level. Much is claimed for the golden ratio φ, but none of the screens pervading our lives use it. Perhaps that’s an accident of technology, but can making screens to φ’s proportions be more difficult or expensive than 2:3 or 3:4 or 16:10? Here, then, is not just one but a set of proportions with a uniquely human focus, originating in nature, recognized in antiquity, fundamental still.
We find music to be an art steeped with meaning, yet, unlike literary and representational arts, purely instrumental music has no obvious semantic content. It boasts an ability to express emotions while remaining an abstract art in some sense, which makes it very like design. These days, we’re rightly encouraged to design for emotion, to make our users’ experience meaningful, seductive, delightful. Using musical ideas and principles in our designs can help achieve those ends.
Let’s not be naïve, of course; designing web pages is even less like composing music than it’s like designing for print. In visual design, the eye will always be sovereign to the ear; following these principles will only get us so far. We cannot truly claim that a carefully composed web page layout will have the same qualities and effect as any musical patterns that inform it. In music, a set of intervals is always harmonious in relation to other sets of intervals: music rarely stands still. What aspect ratios will future screens take? Already today there is great variation in devices and support for media queries (and within that, support for device-aspect-ratio). And what of non-western musical traditions? Or rhythm, form, tempo and dynamics? What I’ve demonstrated above is only a suggestion, a tentative exploration of one possible way forward.
But as our discipline matures and we become more articulate about what we do, we must look longer and deeper into areas of human endeavour already rich with value. Music is a fertile ground to explore and has the potential to yield up new approaches for web design.
Footnotes
Just intonation is a system of tuning that uses small integers to describe the musical intervals, based initially on the perfect fifth, that most consonant of intervals. Simple instruments such as vibrating strings and natural horns, as well as unaccompanied voices, tend to fall into just intonation naturally.",2011,Owen Gregory,owengregory,2011-12-09T00:00:00+00:00,https://24ways.org/2011/composing-the-new-canon/,design
84,Responsive Responsive Design,"Now more than ever, we’re designing work meant to be viewed along a gradient of different experiences. Responsive web design offers us a way forward, finally allowing us to “design for the ebb and flow of things.”
With those two sentences, Ethan closed the article that introduced the web to responsive design. Since then, responsive design has taken the web by storm. Seemingly every day, some company is touting their new responsive redesign. Large brands such as Microsoft, Time and Disney are getting in on the action, blowing away the once common criticism that responsive design was a technique only fit for small blogs.
Certainly, this is a good thing. As Ethan and John Allsopp before him, were right to point out, the inherent flexibility of the web is a feature, not a bug. The web’s unique ability to be consumed and interacted with on any number of devices, with any number of input methods is something to be embraced.
But there’s one part of the web’s inherent flexibility that seems to be increasingly overlooked: the ability for the web to be interacted with on any number of networks, with a gradient of bandwidth constraints and latency costs, on devices with varying degrees of hardware power.
A few months back, Stephanie Rieger tweeted
“Shoot me now…responsive design has seemingly become confused with an opportunity to reduce performance rather than improve it.”
I would love to disagree, but unfortunately the evidence is damning. Consider the size and number of requests for four highly touted responsive sites that were launched this year:
74 requests, 1,511kb
114 requests, 1,200kb
99 requests, 1,298kb
105 requests, 5,942kb
And those numbers were for the small screen versions of each site!
These sites were praised for their visual design and responsive nature, and rightfully so. They’re very easy on the eyes and a lot of thought went into their appearance. But the numbers above tell an inconvenient truth: for all the time spent ensuring the visual design was airtight, seemingly very little (if any) attention was given to their performance.
It would be one thing if these were the exceptions, but unfortunately they’re not. Guy Podjarny, who has done a lot of research around responsive performance, discovered that 86% of the responsive sites he tested were either the same size or larger on the small screen as they were on the desktop.
The reality is that high performance should be a requirement on any web project, not an afterthought. Poor performance has been tied to a decrease in revenue, traffic, conversions, and overall user satisfaction. Case study after case study shows that improving performance, even marginally, will impact the bottom line. The situation is no different on mobile where 71% of people say they expect sites to load as quickly or faster on their phone when compared to the desktop.
The bottom line: performance is a fundamental component of the user experience.
So, given it’s extreme importance in the success of any web project, why is it that we’re seeing so many bloated responsive sites?
First, I adamantly disagree with the belief that poor performance is inherent to responsive design. That’s not a rule – it’s a cop-out. It’s an example of blaming the technique when we should be blaming the implementation. This argument also falls flat because it ignores the fact that the trend of fat sites is increasing on the web in general. While some responsive sites are the worst offenders, it’s hardly an issue resigned to one technique.
To fix the issue, we need to stop making excuses and start making improvements instead. Here, then, are some things we can do to start improving the state of responsive performance, and performance in general, right now.
Create a culture of performance
If you understand just how important performance is to the success of a project, the natural next step is to start creating a culture where high performance is a key consideration.
One of the things you can do is set a baseline. Determine the maximum size and number of requests you are going to allow, and don’t let a page go live if either of those numbers is exceeded. The BBC does this with its responsive mobile site.
A variation of that, which Steve Souders discussed in a recent podcast is to create a performance budget based on those numbers. Once you have that baseline set, if someone comes along and wants to add a something to the page, they have to make sure the page remains under budget. If it exceeds the budget, you have three options:
Optimize an existing feature or asset on the page
Remove an existing feature or asset from the page
Don’t add the new feature or asset
The idea here is that you make performance part of the process instead of something that may or may not get tacked on at the end.
Embrace the pain
This troubling trend of web bloat can be blamed in part on the lack of pain associated with poor performance. Most of us work on high-speed connections with low latency. When we fire up a 4Mb site, it doesn’t feel so bad.
When I tested the previously mentioned 5,942kb site on a 3G network, it took over 93 seconds to load. A minute and a half just staring at a white screen. Had anyone working on that project experienced that, you can bet the site wouldn’t have launched in that state.
Don’t just crunch numbers. Fire up your site on a slower network and see what it feels like to wait. If you don’t have access to a slow network, simulate one using a tool like Slowy, Throttle or the Network Conditioner found in Mac OS X 10.7.
Watch for low-hanging fruit
There are a bunch of general performance improvements that apply to any site (responsive or not) but often aren’t made. A great starting point is to refer to Yahoo!‘s list of rules.
Some of this might sound complicated or intimidating, but it doesn’t have to be. You can grab an .htaccess file from HTML 5 Boilerplate or use Sergey Chernyshev’s drop-in .htaccess file. You can use tools like SpriteMe to simplify the creation of sprites, and ImageOptim to compress images.
Just by implementing these simple optimizations you will achieve a noticeable improvement in terms of weight and page load time.
Be careful with images
The most common offender for poor responsive performance is downloading unnecessarily large images, or worse yet, multiple sizes of the same image.
For background images, simply being careful with where and how you include the image can ensure you don’t get caught in the trap of multiple background images being downloaded without being used. Don’t count on display:none to help. While it may hide elements from displaying on screen, those images will still be requested and downloaded.
Content images can be a little trickier. Whatever you do, don’t serve a large image that works on a large screen display to small screens. It’s wasteful, not only in terms of adding weight to the page, but also in wasting precious memory. Instead, use a tool like Adaptive Images or src.sencha.io to make sure only appropriately sized images are being downloaded.
The new element that has been so often discussed is another excellent solution if you’re feeling particularly future-oriented. A picture polyfill exists so that you can start using the element now without any worries about support.
Conditional loading
Don’t load any more than you absolutely need to. If a script isn’t needed at certain sizes, use the matchMedia polyfill to ensure it only loads when needed. Use eCSSential to do the same for unnecessary CSS files.
Last year on 24 ways, Jeremy Keith wrote an article about conditional loading of content in a responsive design based on the screen width. The technique was later refined by the Filament Group into what they dubbed the Ajax-Include Pattern. It’s a powerful and simple way to lighten the load on small screens as well as reduce clutter.
Go vanilla?
If you take a look at the HTTP Archive you’ll see that other than image size, JavaScript is the heaviest asset on a page weighing in at 215kb on average. It also boasts the fifth highest correlation to load time as well as the second highest correlation to render time.
Much of the weight can be attributed to our industry’s increasing reliance on frameworks. This is especially a concern on mobile devices. PPK recently exclaimed that current JavaScript libraries are just “too heavy for mobile”. “Research from Stoyan Stefanov on parse times supports this. On some Android and iOS devices, it can take as long as 200-300ms just to parse jQuery.
There’s nothing wrong about using a framework, but the problem is that they’ve become the default. Before dropping another framework or plugin into a page, we should stop to consider the value it adds and whether we could accomplish what we need to do using a combination of vanilla JavaScript and CSS instead. (This is a great example of a scenario where a performance budget could help.)
Start thinking beyond visual aesthetics
We love to tout the web’s universality when discussing the need for responsive design. But that universality is not limited simply to screen size. Networks and hardware capabilities must factor in as well.
The web is an incredibly dynamic and interactive medium, and designing for it demands that we consider more than just visual aesthetics. Let’s not forget to give those other qualities the attention they deserve.",2012,Tim Kadlec,timkadlec,2012-12-05T00:00:00+00:00,https://24ways.org/2012/responsive-responsive-design/,design
299,What the Heck Is Inclusive Design?,"Naming things is hard. And I don’t just mean CSS class names and JSON properties. Finding the right term for what we do with the time we spend awake and out of bed turns out to be really hard too.
I’ve variously gone by “front-end developer”, “user experience designer”, and “accessibility engineer”, all clumsy and incomplete terms for labeling what I do as an… erm… see, there’s the problem again.
It’s tempting to give up entirely on trying to find the right words for things, but this risks summarily dispensing with thousands of years spent trying to qualify the world around us. So here we are again.
Recently, I’ve been using the term “inclusive design” and calling myself an “inclusive designer” a lot. I’m not sure where I first heard it or who came up with it, but the terminology feels like a good fit for the kind of stuff I care to do when I’m not at a pub or asleep.
This article is about what I think “inclusive design” means and why I think you might like it as an idea.
Isn’t ‘inclusive design’ just ‘accessibility’ by another name?
No, I don’t think so. But that’s not to say the two concepts aren’t related. Note the ‘design’ part in ‘inclusive design’ — that’s not just there by accident. Inclusive design describes a design activity; a way of designing things.
This sets it apart from accessibility — or at least our expectations of what ‘accessibility’ entails. Despite every single accessibility expert I know (and I know a lot) recommending that accessibility should be integrated into design process, it is rarely ever done. Instead, it is relegated to an afterthought, limiting its effect.
The term ‘accessibility’ therefore lacks the power to connote design process. It’s not that we haven’t tried to salvage the term, but it’s beginning to look like a lost cause. So maybe let’s use a new term, because new things take new names. People get that.
The ‘access’ part of accessibility is also problematic. Before we get ahead of ourselves, I don’t mean access is a problem — access is good, and the more accessible something is the better. I mean it’s not enough by itself.
Imagine a website filled with poorly written and lackadaisically organized information, including a bunch of convoluted and confusing functionality. To make this site accessible is to ensure no barriers prevent people from accessing the content.
But that doesn’t make the content any better. It just means more people get to suffer it.
Whoopdidoo.
Access is certainly a prerequisite of inclusion, but accessibility compliance doesn’t get you all the way there. It’s possible to check all the boxes but still be left with an unusable interface. And unusable interfaces are necessarily inaccessible ones. Sure, you can take an unusable interface and make it accessibility compliant, but that only placates stakeholders’ lawyers, not users. Users get little value from it.
So where have we got to? Access is important, but inclusion is bigger than access. Inclusive design means making something valuable, not just accessible, to as many people as we can.
So inclusive design is kind of accessibility + UX?
Closer, but there are some problems with this definition.
UX is, you will have already noted, a broad term encompassing activities ranging from conducting research studies to optimizing the perceived affordance of interface elements. But overall, what I take from UX is that it’s the pursuit of making interfaces understandable.
As it happens, WCAG 2.0 already contains an ‘Understandable’ principle covering provisions such as readability, predictability and feedback. So you might say accessibility — at least as described by WCAG — already covers UX.
Unfortunately, the criteria are limited, plus some really important stuff (like readability) is relegated to the AAA level; essentially “bonus points if you get the time (you won’t).”
So better to let UX folks take care of this kind of thing. It’s what they do. Except, therein lies a danger. UX professionals don’t tend to be well versed in accessibility, so their ‘solutions’ don’t tend to work for that many people. My friend Billy Gregory coined the term SUX, or “Some UX”: if it doesn’t work for different users, it’s only doing part of the job it should be.
SUX won’t do, but it’s not just a disability issue. All sorts of user circumstances go unchecked when you’re shooting straight for what people like, and bypassing what people need: device type, device settings, network quality, location, native language, and available time to name just a few.
In short, inclusive design means designing things for people who aren’t you, in your situation. In my experience, mainstream UX isn’t very good at that. By bolting accessibility onto mainstream UX we labor under the misapprehension that most people have a ‘normal’ experience, a few people are exceptions, and that all of the exceptions pertain to disability directly.
So inclusive design isn’t really about disability?
It is about disability, but not in the same way as accessibility. Accessibility (as it is typically understood, anyway) aims to make sure things work for people with clinically recognized disabilities. Inclusive design aims to make sure things work for people, not forgetting those with clinically recognized disabilities. A subtle, but not so subtle, difference.
Let’s go back to discussing readability, because that’s a good example. Now: everyone benefits from readable text; text with concise sentences and widely-understood words. It certainly helps people with cognitive impairments, but it doesn’t hinder folks who have less trouble with comprehension. In fact, they’ll more than likely be thankful for the time saved and the clarity. Readable text covers the whole gamut. It’s — you’ve got it — inclusive.
Legibility is another one. A clear, well-balanced typeface makes the reading experience less uncomfortable and frustrating for all concerned, including those who have various forms of visual dyslexia. Again, everyone’s happy — so why even contemplate a squiggly, sketchy typeface? Leave well alone.
Contrast too. No one benefits from low contrast; everyone benefits from high contrast. Simple. There’s no more work involved, it just entails better decision making. And that’s what design is really: decision making.
How about zoom support? If you let your users pinch zoom on their phones they can compensate for poor eyesight, but they can also increase the touch area of controls, inspect detail in images, and compose better screen shots. Unobtrusively supporting options like zoom makes interfaces much more inclusive at very little cost.
And when it comes to the underlying HTML code, you’re in luck: it has already been designed, from the outset, to be inclusive. HTML is a toolkit for inclusion. Using the right elements for the job doesn’t just mean the few who use screen readers benefit, but keyboard accessibility comes out-of-the-box, you can defer to browser behavior rather than writing additional scripts, the code is easier to read and maintain, and editors can create content that is effortlessly presentable.
Wait… are you talking about universal design?
Hmmm. Yes, I guess some folks might think of “universal design” and “inclusive design” as synonymous. I just really don’t like the term universal in this context.
The thing is, it gives the impression that you should be designing for absolutely everyone in the universe. Though few would adopt a literal interpretation of “universal” in this context, there are enough developers who would deliberately misconstrue the term and decry universal design as an impossible task. I’ve actually had people push back by saying, “what, so I’ve got to make it work for people who are allergic to computers? What about people in comas?”
For everyone’s sake, I think the term ‘inclusive’ is less misleading. Of course you can’t make things that everybody can use — it’s okay, that’s not the aim. But with everything that’s possible with web technologies, there’s really no need to exclude people in the vast numbers that we usually are.
Accessibility can never be perfect, but by thinking inclusively from planning, through prototyping to production, you can cast a much wider net. That means more and happier users at very little if any more effort.
If you like, inclusive design is the means and accessibility is the end — it’s just that you get a lot more than just accessibility along the way.
Conclusion
That’s inclusive design. Or at least, that’s a definition for a thing I think is a good idea which I identify as inclusive design. I’ll leave you with a few tips.
Involve code early
Web interfaces are made of code. If you’re not working with code, you’re not working on the interface. That’s not to say there’s anything wrong with sketching or paper prototyping — in fact, I recommend paper prototyping in my book on inclusive design. Just work with code as soon as you can, and think about code even before that. Maintain a pattern library of coded solutions and omit any solutions that don’t adhere to basic accessibility guidelines.
Respect conventions
Your content should be fresh, inventive, radical. Your interface shouldn’t. Adopt accepted conventions in the appearance, placement and coding of interface elements. Users aren’t there to experience interface design; they’re there to use an interface. In other words: stop showing off (unless, of course, the brief is to experiment with new paradigms in interface design, for an audience of interface design researchers).
Don’t be exact
“Perfection is the enemy of good”. But the pursuit of perfection isn’t just to be avoided because nothing ever gets finished. Exacting design also makes things inflexible and brittle. If your design depends on elements retaining precise coordinates, they’ll break easily when your users start adjusting font settings or zooming. Choose not to position elements exactly or give them fixed, “magic number” dimensions. Make less decisions in the interface so your users can make more decisions for it.
Enforce simplicity
The virtue of simplicity is difficult to overestimate. The simpler an interface is, the easier it is to use for all kinds of users. Simpler interfaces require less code to make too, so there’s an obvious performance advantage. There are many design decisions that require user research, but keeping things simple is always the right thing to do. Not simplified or simple-seeming or simplistic, but simple.
Do a little and do it well, for as many people as you can.",2016,Heydon Pickering,heydonpickering,2016-12-07T00:00:00+00:00,https://24ways.org/2016/what-the-heck-is-inclusive-design/,process
58,Beyond the Style Guide,"Much like baking a Christmas cake, designing for the web involves creating an experience in layers. Starting with a solid base that provides the core experience (the fruit cake), we can add further layers, each adding refinement (the marzipan) and delight (the icing).
Don’t worry, this isn’t a misplaced cake recipe, but an evaluation of modular design and the role style guides can play in acknowledging these different concerns, be they presentational or programmatic.
The auteur’s style guide
Although trained as a graphic designer, it was only when I encountered the immediacy of the web that I felt truly empowered as a designer. Given a desire to control every aspect of the resulting experience, I slowly adopted the role of an auteur, exploring every part of the web stack: front-end to back-end, and everything in between. A few years ago, I dreaded using the command line. Today, the terminal is a permanent feature in my Dock.
In straddling the realms of graphic design and programming, it’s the point at which they meet that I find most fascinating, with each dicipline valuing the creation of effective systems, be they for communication or code efficiency. Front-end style guides live at this intersection, demonstrating both the modularity of code and the application of visual design.
Painting by numbers
In our rush to build modular systems, design frameworks have grown in popularity. While enabling quick assembly, these come at the cost of originality and creative expression – perhaps one reason why we’re seeing the homogenisation of web design.
In editorial design, layouts should accentuate content and present it in an engaging manner. Yet on the web we see a practice that seeks templated predictability. In ‘Design Machines’ Travis Gertz argued that (emphasis added):
Design systems still feel like a novelty in screen-based design. We nerd out over grid systems and modular scales and obsess over style guides and pattern libraries. We’re pretty good at using them to build repeatable components and site-wide standards, but that’s sort of where it ends. […] But to stop there is to ignore the true purpose and potential of a design system.
Unless we consider how interface patterns fully embrace the design systems they should be built upon, style guides may exacerbate this paint-by-numbers approach, encouraging conformance and suppressing creativity.
Anatomy of a button
Let’s take a look at that most canonical of components, the button, and consider what we might wish to document and demonstrate in a style guide.
The different layers of our button component.
Content
The most variable aspect of any component. Content guidelines will exert the most influence here, dictating things like tone of voice (whether we should we use stiff, formal language like ‘Submit form’, or adopt a more friendly tone, perhaps ‘Send us your message’) and appropriate language. For an internationalised interface, this may also impact word length and text direction or orientation.
Structure
HTML provides a limited vocabulary which we can use to structure content and add meaning. For interactive elements, the choice of element can also affect its behaviour, such as whether a button submits form data or links to another page:
Button text
Button text
Note: One of the reasons I prefer to use instead of , besides allowing the inclusion of content other than text, is that it has a markup structure similar to links, therefore keeping implementation differences to a minimum.
We should also think about each component within the broader scope of our particular product. For this we can employ a further vocabulary, which can be expressed by adding values to the class attribute. For a newspaper, we might use names like lede, standfirst and headline, while a social media application might see us reach for words like stream, action or avatar.
Presentation
The appearance of a component can never be considered in isolation. Informed by its relationship to other elements, style guides may document different stylistic variations of a component, even if the underlying function remains unchanged: primary and secondary button styles, for example.
Behaviour
A component can exhibit various states: blank, loading, partial, error and ideal, and a style guide should reflect that. Our button component is relatively simple, yet even here we need to consider hover, focused, active and disabled states.
Transcending layers
This overview reinforces Ethan’s note from earlier in this series:
I’ve found that thinking about my design as existing in broad experience tiers – in layers – is one of the best ways of designing for the modern web.
While it’s tempting to describe a component as series of layers, certain aspects will transcend several of these. The accessibility of a component, for example, may influence the choice of language, the legibility of text, colour contrast and which affordances are provided in different states.
Visual design language: documenting the missing piece
Even given this small, self-contained component, we can see several concerns at play, and in reviewing our button it seems we have most things covered. However, a few questions remain unanswered. Why does it have a blue background? Why are the borders 2px thick, with a radius of 4px? Why are we using that font, at that size and with that weight?
These questions can be answered by our visual design language. More than a set of type choices and colour palettes, a design language can dicate common measures, ratios and the resulting grid(s) these influence. Ideally governed by a set of broader design principles, it can also inform an illustration style, the type of photography sourced or commissioned, and the behaviour of any animations.
Whereas a style guide ensures conformity, having it underpinned by an effective design language will allow for flexibility; only by knowing the rules can you know how to break them!
Type pairings in the US Web Design Standards guide.
For a style guide to thoroughly articulate a visual design system, the spectrum of choices it allows for should be acknowledged. A fantastic example of this can be found in the US Web Design Standards. By virtue of being a set of standards designed to apply to a number of different sites, this guide offers a range of type pairings (that take into account performance considerations) and provides primary, secondary and tertiary palette relationships, with shades and tones thereof:
Colour palettes in the US Web Design Standards guide.
A visual language in code form
Properly documenting our design language in a style guide is a good start, yet even better if it can be expressed in code. This is where CSS preprocessors become a powerful ally.
In Sass, methods like mixins and maps can help us represent relationships between values. Variables (and CSS variables) extend the vocabulary provided natively by CSS, meaning we can describe patterns in terms of our own visual language. These tools effectively become an interface to our design system. Furthermore, they help maintain a separation of concerns, with visual presentation remaining where it should be: in our style sheets.
Take this simple example, an article summary on a website counting down the best Christmas movies:
The design for our simple component example.
Our markup is as follows, using appropriate semantic HTML elements and incorporating the vocabulary from our collection of design patterns (expressed using the BEM methodology):
It’s unlikely that Bill Murray could ever have got through his career without playing a version of Scrooge…
Director: Richard Donner
Stars: Bill Murray, Buddy Hackett, Karen Allen
We can then describe the presentation of this HTML by using Sass maps to define our palettes, mixins to include predefined font metrics, and variables to recall common measurements:
.summary {
margin-bottom: ($baseline * 4)
}
.summary__title {
@include font-family(display-serif);
@include font-size(title);
color: palette(neutral, dark);
margin-bottom: ($baseline * 4);
border-top: $rule-height solid palette(primary, purple);
padding-top: ($baseline * 2);
}
.summary__position {
@include font-family(display-sans, 300);
color: palette(neutral, mid);
}
.summary__body {
@include font-family(text-serif);
@include font-size(body);
margin-bottom: ($baseline * 2);
}
.summary__meta {
@include font-family(text-sans);
@include font-size(caption);
}
Of course, this is a simplistic example for the purposes of demonstration. However, such thinking was employed at a much larger scale at the Guardian. Using a set of Sass components, complex patterns could be described using a language familar to everyone on the product team, be they a designer, developer or product owner:
The design of a component on the Guardian website, described in terms of its Sass-powered design system.
Unlocking possibility
Alongside tools like preprocessors, newer CSS layout modules like flexbox and grid layout mean the friction we’ve long been accustomed to when creating layouts on the web is no longer present, and the full separation of presentation from markup is now possible. Now is the perfect time for graphic designers to advocate design systems that these developments empower, and ensure they’re fully represented in both documentation and code. That way, together, we can build systems that allow for greater visual expression. After all, there’s more than one way to bake a Christmas cake.",2015,Paul Lloyd,paulrobertlloyd,2015-12-16T00:00:00+00:00,https://24ways.org/2015/beyond-the-style-guide/,design
34,Collaborative Responsive Design Workflows,"Much has been written about workflow and designer-developer collaboration in web design, but many teams still struggle with this issue; either with how to adapt their internal workflow, or how to communicate the need for best practices like mobile first and progressive enhancement to their teams and clients. Christmas seems like a good time to have another look at what doesn’t work between us and how we can improve matters.
Why is it so difficult?
We’re still beginning to understand responsive design workflows, acknowledging the need to move away from static design tools and towards best practices in development. It’s not that we don’t want to change – so why is it so difficult?
Changing the way we do something that has become routine is always problematic, even with small things, and the changes today’s web environment requires from web design and development teams are anything but small.
Although developers also have a host of new skills to learn and things to consider, designers are probably the ones pushed furthest out of their comfort zones: as well as graphic design, a web designer today also needs an understanding of interaction design and ergonomics, because more and more websites are becoming tools rather than pages meant to be read like a book or magazine. In addition to that there are thousands of different devices and screen sizes on the market today that layout and interactions need to work on.
These aspects make it impossible to design in a static design tool, so beyond having to learn about new aspects of design, the designer has to either learn how to code or learn to work with a responsive design tool.
Why do it
That alone is enough to leave anyone overwhelmed, as learning a new skill takes time and slows you down in a project – and on most projects time is in short supply. Yet we have to make time or fall behind in the industry as others pitch better, interactive designs. For an efficient workflow, both designers and developers must familiarise themselves with new tools and techniques.
A designer has to be able to play with ideas, make small adjustments here and there, look at the result, go back to the settings and make further adjustments, and so on. You can only realistically do that if you are able to play with all the elements of a design, including interactivity, accessibility and responsiveness.
Figuring out the right breakpoints in a layout is one of the foremost reasons for designing in a responsive design tool. Even if you create layouts for three viewport sizes (i.e. smartphone, tablet and the most common desktop size), you’d only cover around 30% of visitors and you might miss problems like line breaks and padding at other viewport sizes.
Another advantage is consistency. In static design tools changes will not be applied across all your other layouts. A developer referring back to last week’s comps might work with outdated metrics. Furthermore, you cannot easily test what impact changes might have on previously designed areas. In a dynamic design tool such changes will be applied to the entire design and allow you to test things in site areas you had already finished.
No static design tool allows you to do this, and having somebody else produce a mockup from your static designs or wireframes will duplicate work and is inefficient.
How to do it
When working in a responsive design tool rather than in the browser, there is still the question of how and when to communicate with the developer. I have found that working with Sass in combination with a visual style guide is very efficient, but it does need careful planning: fundamental metrics for padding, margins and font sizes, but also design elements like sliders, forms, tabs, buttons and navigational elements, should be defined at the beginning of a project and used consistently across the site. Working with a grid can help you develop a consistent design language across your site.
Create a visual style guide that shows what the elements look like and how they behave across different screen sizes – and when interacted with. Put all metrics on paddings, margins, breakpoints, widths, colours and so on in a text document, ideally with names that your developer can use as Sass variables in the CSS. For example:
$padding-default-vertical: 1.5em;
Developers, too, need an efficient workflow to keep code maintainable and speed up the time needed for more complex interactions with an eye on accessibility and performance. CSS preprocessors like Sass allow you to work with variables and mixins for default rules, as well as style sheet partials for different site areas or design elements. Create your own boilerplate to use for your projects and then update your variables with the information from your designer for each individual project.
How to get buy-in
One obstacle when implementing responsive design, accessibility and content strategy is the logistics of learning new skills and iterating on your workflow. Another is how to sell it. You might expect everyone on a project (including the client) to want to design and develop the best website possible: ultimately, a great site will lead to more conversions. However, we often hear that people find it difficult to convince their teammates, bosses or clients to implement best practices.
Why is that? Well, I believe a lot of it is down to how we sell it. You will have experienced this yourself: some people you trust to know what they are talking about, and others you don’t. Think about why you trust that first person but don’t buy what the other one is telling you. It is likely because person A has a self-assured, calm and assertive demeanour, while person B seems insecure and apologetic. To sell our ideas, we need to become person A! For a timid designer or developer suffering from imposter syndrome (like many of us do in this industry) that is a difficult task. So how can we become more confident in selling our expertise?
Write
We need to become experts. And I mean not just in writing great code or coming up with beautiful designs but at explaining why we’re doing what we’re doing. Why do you code this way or that? Why is this the best layout? Why does a website have to be accessible and responsive? Write about it. Putting your thoughts down on paper or screen is a really efficient way of getting your head around a topic and learning to make a case for something. You may even find that you come up with new ideas as you are writing, so you’ll become a better designer or developer along the way.
Talk
Then, talk about it. Start out in front of your team, then do a lightning talk at a web event near you, then a longer talk or workshop. Having to talk about a topic is going to help you put into spoken words the argument that you’ve previously put together in writing. Writing comes more easily when you’re starting out but we use a different register when writing than talking and you need to learn how to speak your case. Do the talk a couple of times and after each talk make adjustments where you found it didn’t work well. By this time, you are more than ready to make your case to the client. In fact, you’ve been ready since that first talk in front of your colleagues ;)
Pitch
Pitches used to be based on a presentation of static layouts for for three to five typical pages and three different designs. But if we want to sell interactivity, structure, usability, accessibility and responsiveness, we need to demonstrate these things and I believe that it can only do us good. I have seen a few pitches sitting in the client’s chair and static layouts are always sort of dull. What makes a website a website is the fact that I can interact with it and smooth interactions or animations add that extra sparkle.
I can’t claim personal experience for this one but I’d be bold and go for only one design. One demo page matching the client’s corporate design but not any specific page for the final site. Include design elements like navigation, photography, typefaces, article layout (with real content), sliders, tabs, accordions, buttons, forms, tables (yes, tables) – everything you would include in a style tiles document, only interactive. Demonstrate how the elements behave when clicked, hovered and touched, and how they change across different screen sizes. You may even want to demonstrate accessibility features like tabbed navigation and screen reader use.
Obviously, there are many approaches that will work in different situations but don’t give up on finding a process that works for you and that ultimately allows you to build delightful, accessible, responsive user experiences for the web. Make time to try new tools and techniques and don’t just work on them on the side – start using them on an actual project. It is only when we use a tool or process in the real world that we become true experts. Remember your driving lessons: once the instructor had explained how to operate the car, you were sent to practise driving on the road in actual traffic!",2014,Sibylle Weber,sibylleweber,2014-12-07T00:00:00+00:00,https://24ways.org/2014/collaborative-responsive-design-workflows/,process
57,Cooking Up Effective Technical Writing,"Merry Christmas! May your preparations for this festive season of gluttony be shaping up beautifully. By the time you read this I hope you will have ordered your turkey, eaten twice your weight in Roses/Quality Street (let’s not get into that argument), and your Christmas cake has been baked and is now quietly absorbing regular doses of alcohol.
Some of you may be reading this and scoffing Of course! I’ve also made three batches of mince pies, a seasonal chutney and enough gingerbread men to feed the whole street! while others may be laughing Bake? Oh no, I can’t cook to save my life.
For beginners, recipes are the step-by-step instructions that hand-hold us through the cooking process, but even as a seasoned expert you’re likely to refer to a recipe at some point. Recipes tell us what we need, what to do with it, in what order, and what the outcome will be. It’s the documentation behind our ideas, and allows us to take the blueprint for a tasty morsel and to share it with others so they can recreate it. In fact, this is a little like the open source documentation and tutorials that we put out there, similarly aiming to guide other developers through our creations.
The ‘just’ification of documentation
Lately it feels like we’re starting to consider the importance of our words, and the impact they can have on others. Brad Frost warned us of the dangers of “Just” when it comes to offering up solutions to queries:
“Just use this software/platform/toolkit/methodology…”
“Just” makes me feel like an idiot. “Just” presumes I come from a specific background, studied certain courses in university, am fluent in certain technologies, and have read all the right books, articles, and resources. “Just” is a dangerous word.
“Just” by Brad Frost
I can really empathise with these sentiments. My relationship with code started out as many good web tales do, with good old HTML, CSS and JavaScript. University years involved some time with Perl, PHP, Java and C. In my first job I worked primarily with ColdFusion, a bit of ActionScript, some classic ASP and pinch of Java. I’d do a bit of PHP outside work every now and again. .NET came in, but we never really got on, and eventually I started learning some Ruby, Python and Node. It was a broad set of learnings, and I enjoyed the similarities and differences that came with new languages. I don’t develop day in, day out any more, and my interests and work have evolved over the years, away from full-time development and more into architecture and strategy. But I still make things, and I still enjoy learning.
I have often found myself bemoaning the lack of tutorials or courses that cater for the middle level – someone who may be learning a new language, but who has enough programming experience under their belt to not need to revise the concepts of how loops or objects work, and is perfectly adept at googling the syntax for getting a substring. I don’t want snippets out of context; I want an understanding of architectural principles, of the strengths and weaknesses, of the type of applications that work well with the language.
I’m caught in the place between snoozing off when ‘Using the Instagram API with Ruby’ hand-holds me through what REST is, and feeling like I’m stupid and need to go back to dev school when I can’t get my environment and dependencies set up, let alone work out how I’m meant to get any code to run.
It’s seems I’m not alone with this – Erin McKean seems to have been here too:
“Some tutorials (especially coding tutorials) like to begin things in media res. Great for a sense of dramatic action, bad for getting to “Step 1” without tears. It can be really discouraging to fire up a fresh terminal window only to be confronted by error message after error message because there were obligatory steps 0.1.0 through 0.9.9 that you didn’t even know about.”
“Tips for Learning What You Don’t Know You Don’t Know” by Erin McKean
I’m sure you’ve been here too. Many tutorials suffer badly from the fabled ‘how to draw an owl’-itis.
It’s the kind of feeling you can easily get when sifting through recipes as well as with code. Far from being the simple instructions that let us just follow along, they too can be a minefield. Fall in too low and you may be skipping over an explanation of what simmering is, or set your sights too high and you may get stuck at the point where you’re trying to sous vide a steak using your bathtub and a Ziploc bag.
Don’t be a turkey, use your loaf!
My mum is a great cook in my eyes (aren’t all mums?). I love her handcrafted collection of gathered recipes from over the years, including the one below, which is a great example of how something may make complete sense to the writer, but could be impermeable to a reader.
Depending on your level of baking knowledge, you may ask: What’s SR flour? What’s a tsp? Should I use salted or unsalted butter? Do I use sticks of cinnamon or ground? Why is chopped chocolate better? How do I cream things? How big should the balls be? How well is “well spaced”? How much leeway do I have for “(ish!!)”? Does the “20” on the other cookie note mean I’ll end up with twenty? At any point, making a wrong call could lead to rubbish cookies, and lead to someone heading down the path of an I can’t cook mentality.
You may be able to cook (or follow recipes), but you may not understand the local terms for ingredients, may not be able to acquire something and need to know what kind of substitutes you can use, or may need to actually do some prep before you jump into the main bit.
However, if we look at good examples of recipes, I think there’s a lot we can apply when it comes to technical writing on the web. I’ve written before about the benefit of breaking documentation into small, reusable parts, and this will help us, but we can also take it a bit further. Here are my five top tips for better technical writing.
1. Structure and standardise your information
Think of the structure of a recipe. We very often have some common elements and they usually follow roughly the same format. We have standards and conventions that allow us to understand very quickly what a recipe is and how it should be used.
Great recipes help their chefs know what they need to get ready in advance, both in terms of buying ingredients and putting together their kit. They then talk through the process, using appropriate language, and without making assumptions that the person can fill in any gaps for themselves; they explain why things are done the way they are. The best recipes may also suggest how you can take what you’ve done and put your own spin on it. For instance, a good recipe for the simple act of boiling an egg will explain cooking time in relation to your preference for yolk gooiness. There are also different flavour combinations to try, accompaniments, or presentation suggestions.
By breaking down your technical writing into similar sections, you can help your audience understand the elements they’ll be working with, what they need to do once they have these, and how they can move on from your self-contained illustration.
Title
Ensure your title is suitably descriptive and representative of the result. Getting Started with Python perhaps isn’t as helpful as Learn Python: General Syntax and Basics.
Result
Many recipes include a couple of lines as an overview of what you’ll end up with, and many include a photo of the finished dish. With our technical writing we can do the same:
In this tutorial we’re going to learn how to set up our development environment, and we’ll then undertake some exercises to explore the general syntax, finishing by building a mini calculator.
Ingredients
What are the components we’ll be working with, whether in terms of versions, environment, languages or the software packages and libraries you’ll need along the way? Listing these up front gives the reader a great summary of the things they’ll be using, and any gotchas.
Being able to provide a small amount of supporting information will also help less experienced users. Ideally, explain briefly what things are and why we’re using it.
Prep
As we heard from Erin above, not fully understanding the prep needed can be a huge source of frustration. Attempting to run a code snippet without context will often lead to failure when the prerequisites and process aren’t clear. Be sure to include information around any environment set-up, installation or config you’ll need to have done before you start.
Stu Robson’s Simple Sass documentation aims to do this before getting into specifics, although ideally this would also include setting up Sass itself.
Instructions
The body of the tutorial itself is the whole point of our writing. The next four tips will hopefully make your tutorial much more successful.
Variations
Like our ingredients section, as important as explaining why we’re using something in this context is, it’s also great to explain alternatives that could be used instead, and the impact of doing so.
Perhaps go a step further, explaining ways that people can change what you have done in your tutorial/readme for use in different situations, or to provide further reading around next steps. What happens if they want to change your static array of demo data to use JSON, for instance? By giving some thought to follow-up questions, you can better support your readers.
While not in a separate section, the source code for GreenSock’s GSAP JS basics explains:
We’ll use a window.onload for simplicity, but typically it is best to use either jQuery’s $(document).ready() or $(window).load() or cross-browser event listeners so that you’re not limited to one.
Keep in mind to both:
Explain what variations are possible.
Explain why certain options may be more desirable than others in different situations.
2. Small, reusable components
Reusable components are for life, not just for Christmas, and they’re certainly not just for development. If you start to apply the structure above to your writing, you’re probably going to keep coming across the same elements: Do I really have to explain how to install Sass and Node.js again, Sally? The danger with more clarity is that our writing becomes bloated and overly convoluted for advanced readers, those who don’t need to be told how to beat an egg for the hundredth time.
Instead, by making our writing reusable and modular, and by creating smaller, central resources, we can provide context and extra detail where needed without diluting our core message. These could be references we create, or those already created well by others.
This recipe for katsudon makes use of this concept. Rather than explaining how to make tonkatsu or dashi stock, these each have their own page. Once familiar, more advanced readers will likely skip over the instructions for the component parts.
3. Provide context to aid accessibility
Here I’m talking about accessibility in the broadest sense. Small, isolated snippets can be frustrating to those who don’t fully understand the wider context of how our examples work.
Showing an exciting standalone JavaScript function is great, but giving someone the full picture of how and when this is called, and how it should be included in relation to other HTML and CSS is even better. Giving your readers the ability to view a big picture version, and ideally the ability to download a full version of the source, will help to reduce some of the frustrations of trying to get your component to work in their set-up.
4. Be your own tech editor
A good editor can be invaluable to your work, and wherever possible I’d recommend that you try to get a neutral party to read over your writing. This may not always be possible, though, and you may need to rely on yourself to cast a critical eye over your work.
There are many tips out there around general editing, including printing out your work onto paper, or changing the font size: both will force your eyes to review it in a new light. Beyond this, I’d like to encourage you to think about the following:
Explain what things are. For example, instead of referencing Grunt, in the first instance perhaps reference “Grunt (a JavaScript task runner that minimises repetitive activities through automation).”
Explain how you get things, even if this is a link to official installers and documentation. Don’t leave your readers having to search.
Why are you using this approach/technology over other options?
What happens if I use something else? What depends on this?
Avoid exclusionary lingo or acronyms.
Airbnb’s JavaScript Style Guide includes useful pointers around their reasoning:
Use computed property names when creating objects with dynamic property names.
Why? They allow you to define all the properties of an object in one place.
The language we use often makes assumptions, as we saw with “just”. An article titled “ES6 for Beginners” is hugely ambiguous: is this truly for beginner coders, or actually for people who have a good pre-existing understanding of JavaScript but are new to these features? Review your writing with different types of readers in mind. How might you confuse or mislead them? How can you better answer their questions?
This doesn’t necessarily mean supporting everyone – your audience may need to have advanced skills – but even if you’re providing low-level, deep-dive, reference material, trying not to make assumptions or take shortcuts will hopefully lead to better, clearer writing.
5. A picture is worth a thousand words…
…or even better: use a thousand pictures, stitched together into a quick video or animated GIF. People learn in different ways. Just as recipes often provide visual references or a video to work along with, providing your technical information with alternative demonstrations can really help get your point across. Your audience will be able to see exactly what you’re doing, what they should expect as interaction responses, and what the process looks like at different points.
There are many, many options for recording your screen, including QuickTime Player on Mac OS X (File → New Screen Recording), GifGrabber, or Giffing Tool on Windows.
Paul Swain, a UX designer, uses GIFs to provide additional context within his documentation, improving communication:
“My colleagues (from across the organisation) love animated GIFs. Any time an interaction is referenced, it’s accompanied by a GIF and a shared understanding of what’s being designed. The humble GIF is worth so much more than a thousand words; and it’s great for cats.”
Paul Swain
Next time you’re cooking up some instructions for readers, think back to what we can learn from recipes to help make your writing as accessible as possible. Use structure, provide reusable bitesize morsels, give some context, edit wisely, and don’t scrimp on the GIFs. And above all, have a great Christmas!",2015,Sally Jenkinson,sallyjenkinson,2015-12-18T00:00:00+00:00,https://24ways.org/2015/cooking-up-effective-technical-writing/,content
275,Context First: Web Strategy in Four Handy Ws,"Many, many years ago, before web design became my proper job, I trained and worked as a journalist. I studied publishing in London and spent three fun years learning how to take a few little nuggets of information and turn them into a story. I learned a bunch of stuff that has all been a huge help to my design career. Flatplanning, layout, typographic theory. All of these disciplines have since translated really well to web design, but without doubt the most useful thing I learned was how to ask difficult questions.
Pretty much from day one of journalism school they hammer into you the importance of the Five Ws. Five disarmingly simple lines of enquiry that eloquently manage to provide the meat of any decent story. And with alliteration thrown in too. For a young journo, it’s almost too good to be true.
Who? What? Where? When? Why? It seems so obvious to almost be trite but, fundamentally, any story that manages to answer those questions for the reader is doing a pretty good job. You’ll probably have noticed feeling underwhelmed by certain news pieces in the past – disappointed, like something was missing. Some irritating oversight that really lets the story down. No doubt it was one of the Ws – those innocuous little suckers are generally only noticeable by their absence, but they sure get missed when they’re not there.
Question everything
I’ve always been curious. An inveterate tinkerer with things and asker of dopey questions, often to the point of abject annoyance for anyone unfortunate enough to have ended up in my line of fire. So, naturally, the Five Ws started drifting into other areas of my life. I’d scrutinize everything, trying to justify or explain my rationale using these Ws, but I’d also find myself ripping apart the stuff that clearly couldn’t justify itself against the same criteria.
So when I started working as a designer I applied the same logic and, sure enough, the Ws pretty much mapped to the exact same needs we had for gathering requirements at the start of a project. It seemed so obvious, such a simple way to establish the purpose of a product. What was it for? Why we were making it? And, of course, who were we making it for? It forced clients to stop and think, when really what they wanted was to get going and see something shiny. Sometimes that was a tricky conversation to have, but it’s no coincidence that those who got it also understood the value of strategy and went on to have good solid products, while those that didn’t often ended up with arrogantly insular and very shiny but ultimately unsatisfying and expendable products. Empty vessels make the most noise and all that…
Content first
I was both surprised and pleased when the whole content first idea started to rear its head a couple of years back. Pleased, because without doubt it’s absolutely the right way to work. And surprised, because personally it’s always been the way I’ve done it – I wasn’t aware there was even an alternative way. Content in some form or another is the whole reason we were making the things we were making. I can’t even imagine how you’d start figuring out what a site needs to do, how it should be structured, or how it should look without a really good idea of what that content might be. It baffles me still that this was somehow news to a lot of people. What on earth were they doing? Design without purpose is just folly, surely?
It’s great to see the idea gaining momentum but, having watched it unfold, it occurred to me recently that although it’s fantastic to see a tangible shift in thinking – away from those bleak times, where making things up was somehow deemed an appropriate way to do things – there’s now a new bad guy in town.
With any buzzword solution of the moment, there’s always a catch, and it seems like some have taken the content first approach a little too literally. By which I mean, it’s literally the first thing they do. The project starts, there’s a very cursory nod towards gathering requirements, and off they go, cranking content. Writing copy, making video, commissioning illustrations.
All that’s happened is that the ‘making stuff up’ part has shifted along the line, away from layout and UI, back to the content.
Starting is too easy
I can’t remember where I first heard that phrase, but it’s a great sentiment which applies to so much of what we do on the web. The medium is so accessible and to an extent disposable; throwing things together quickly carries far less burden than in any other industry. We’re used to tweaking as we go, changing bits, iterating things into shape. The ubiquitous beta tag has become the ultimate caveat, and has made the unfinished and unpolished acceptable. Of course, that can work brilliantly in some circumstances. Occasionally, a product offers such a paradigm shift it’s beyond the level of deep planning and prelaunch finessing we’d ideally like. But, in the main, for most client sites we work on, there really is no excuse not to do things properly. To ask the tricky questions, to challenge preconceptions and really understand the Ws behind the products we’re making before we even start.
The four Ws
For product definition, only four of the five Ws really apply, although there’s a lot of discussion around the idea of when being an influencing factor. For example, the context of a user’s engagement with your product is something you can make a call on depending on the specifics of the project.
So, here’s my take on the four essential Ws. I’ll point out here that, of course, these are not intended to be autocratic dictums. Your needs may differ, your clients’ needs may differ, but these four starting points will get you pretty close to where you need to be.
Who
It’s surprising just how many projects start without a real understanding of the intended audience. Many clients think they have an idea, but without really knowing – it’s presumptive at best, and we all know what presumption is the mother of, right? Of course, we can’t know our audiences in the same way a small shop owner might know their customers. But we can at least strive to find out what type of people are likely to be using the product. I’m not talking about deep user research. That should come later.
These are the absolute basics. What’s the context for their visit? How informed are they? What’s their level of comprehension? Are they able to self-identify and relate to categories you have created? I could go on, and it changes on a per-project basis. You’ll only find this out by speaking to them, if not in person, then indirectly through surveys, questionnaires or polls. The mechanism is less important than actually reaching out and engaging with them, because without that understanding it’s impossible to start to design with any empathy.
What
Once you become deeply involved directly with a product or service, it’s notoriously difficult to see things as an outsider would. You learn the thing inside and out, you develop shortcuts and internal phraseology. Colloquialisms creep in. You become too close. So it’s no surprise when clients sometimes struggle to explain what it is their product actually does in a way that others can understand.
Often products are complex but, really, the core reasons behind someone wanting to use that product are very simple. There’s a value proposition for the customer and, if they choose to engage with it, there’s a value exchange. If that proposition or exchange isn’t transparent, then people become confused and will likely go elsewhere. Make sure both your client and you really understand what that proposition is and, in turn, what the expected exchange should be. In a nutshell: what is the intended outcome of that engagement? Often the best way to do this is strip everything back to nothing. Verbosity is rife on the web. Just because it’s easy to create content, that shouldn’t be a reason to do so. Figure out what the value proposition is and then reintroduce content elements that genuinely help explain or present that to a level that is appropriate for the audience.
Why
In advertising, they talk about the truths behind a product or service. Truths can be both tangible or abstract, but the most important part is the resonance those truths hit with a customer. In a digital product or service those truths are often exposed as benefits. Why is this what I need? Why will it work for me? Why should I trust you? The why is one of the more fluffy Ws, yet it’s such an important one to nail. Clients can get prickly when you ask them to justify the why behind their product, but it’s a fantastic way to make sure the value proposition is clear, realistic and meets with the expectations of both client and customer.
It’s our job as designers to question things: we’re not just a pair of hands for clients. Just recently I spoke to a potential client about a site for his business. I asked him why people would use his product and also why his product seemed so fractured in its direction. He couldnt answer that question so, instead of ploughing on regardless, he went back to his directors and is now re-evaluating that business. It was awkward but he thanked me and hopefully he’ll have a better product as a result.
Where
In this instance, where is not so much a geographical thing, although in some cases that level of context may indeed become a influencing factor… The where we’re talking about here is the position of the product in relation to others around it. By looking at competitors or similar services around the one you are designing, you can start to get a sense for many of the things that are otherwise hard to pin down or have yet to be defined. For example, in a collection of sites all selling cars, where does yours fit most closely? Where are the overlaps? How are they communicating to their customers? How is the product range presented or categorized?
It’s good to look around and see how others are doing it. Not in a quest for homogeneity but more to reference or to avoid certain patterns that may or may not make sense for your own particular product. Clients often strive to be different for the sake of it. They feel they need to provide distinction by going against the flow a bit. We know different. We know users love convention. They embrace familiar mental models. They’re comfortable with things that they’ve experienced elsewhere. By showing your client that position is a vital part of their strategy, you can help shape their product into something great.
To conclude
So there we have it – the four Ws. Each part tells a different and vital part of the story you need to be able to make a really good product. It might sound like a lot of work, particularly when the client is breathing down your neck expecting to see things, but without those pieces in place, the story you’re building your product on, and the content that you’re creating to form that product can only ever fit into one genre. Fiction.",2011,Alex Morris,alexmorris,2011-12-10T00:00:00+00:00,https://24ways.org/2011/context-first/,content
28,Why You Should Design for Open Source,"Let’s be honest. Most designers don’t like working for nothing. We rally against spec work and make a stand for contracts and getting paid. That’s totally what you should do as a professional designer in the industry. It’s your job. It’s your hard-working skill. It’s your bread and butter. Get paid.
However, I’m going to make a case for why you could also consider designing for open source. First, I should mention that not all open source work is free work. Some companies hire open source contributors to work on their projects full-time, usually because that project is used by said company. There are other companies that encourage open source contribution and even offer 20%-time for these projects (where you can spend one day a week contributing to open source). These are super rad situations to be in. However, whether you’re able to land a gig doing this type of work, or you’ve decided to volunteer your time and energy, designing for open source can be rewarding in many other ways.
Portfolio building
New designers often find themselves in a catch-22 situation: they don’t have enough work experience showcased in their portfolio, which leads to them not getting much work because their portfolio is bare. These new designers often turn to unsolicited redesigns to fill their portfolio. An unsolicited redesign is a proof of concept in which a designer attempts to redesign a popular website. You can see many of these concepts on sites like Dribbble and Behance and there are even websites dedicated to showcasing these designs, such as Uninvited Designs. There’s even a subreddit for them.
There are quite a few negative opinions on unsolicited redesigns, though some people see things from both sides. If you feel like doing one or two of these to fill your portfolio, that’s of course up to you. But here’s a better suggestion. Why not contribute design for an open source project instead?
You can easily find many projects in great need of design work, from branding to information design, documentation, and website or application design. The benefits to doing this are far better than an unsolicited redesign. You get a great portfolio piece that actually has greater potential to get used (especially if the core team is on board with it). It’s a win-win situation.
Not all designers are in need of portfolio filler, but there are other benefits to contributing design.
Giving back to the community
My first experience with voluntary work was when I collaborated with my friend, Vineet Thapar, on a pro bono project for the W3C’s Web Accessibility Initiative redesign project back in 2004. I was very excited to contribute CSS to a website that would get used by the W3C! Unfortunately, it decided to go a different direction and my work did not get used. However, it was still pretty exciting to have the opportunity, and I don’t regret a moment of that work. I learned a lot about accessibility from this experience and it helped me land some of the jobs I’ve had since.
Almost a decade later, I got super into Sass. One of the core maintainers, Chris Eppstein, lamented on Twitter one day that the Sass website and brand was in dire need of design help. That led to the creation of an open source task force, Team Sass Design, and we revived the brand and the website, which launched at SassConf in 2013.
It helped me in my current job. I showed it during my portfolio review when I interviewed for the role. Then I was able to use inspiration from a technique I’d tried on the Sass website to help create the more feature-rich design system that my team at work is building. But most importantly, I soon learned that it is exhilarating to be a part of the Sass community. This is the biggest benefit of all. It feels really good to give back to the technology I love and use for getting my work done.
Ben Werdmuller writes about the need for design in open source. It’s great to see designers contributing to open source in awesome ways. When A List Apart’s website went open source, Anna Debenham contributed by helping build its pattern library. Bevan Stephens worked with FontForge on the design of its website. There are also designers who have created their own open source projects. There’s Dan Cederholm’s Pears, which shares common patterns in markup and style. There’s also Brad Frost’s Pattern Lab, which shares his famous method of atomic design and applies it to a design system. These systems and patterns have been used in real-world projects, such as RetailMeNot, so designers have contributed to the web in an even larger way simply by putting their work out there for others to use. That’s kind of fun to think about.
How to get started
So are you stoked about getting into the open source community? That’s great!
Initially, you might get worried or uncomfortable in getting involved. That’s okay. But first consider that the project is open source for a reason. Your contribution (no matter how large or small) can help in a big way.
If you find a project you’re interested in helping, make sure you do your research. Sometimes project team members will be attached to their current design. Is there already a designer on the core team? Reach out to that designer first. Don’t be too aggressive with why you think your design is better than theirs. Rather, offer some constructive feedback and a proposal of what would make the design better. Chances are, if the designer cares about the project, and you make a strong case, they’ll be up for it.
Are there contribution guidelines? It’s proper etiquette to read these and follow the community’s rules. You’ll have a better chance of getting your work accepted, and it shows that you take the time to care and add to the overall quality of the project. Does the project lack guidelines? Consider starting a draft for that before getting started in the design.
When contributing to open source, use your initiative to solve problems in a manageable way. Huge pull requests are hard to review and will often either get neglected or rejected. Work in small, modular, and iterative contributions.
So this is my personal take on what I’ve learned from my experience and why I love open source. I’d love to hear from you if you have your own experience in doing this and what you’ve learned along the way as well. Please share in the comments!
Thanks Drew McLellan, Eric Suzanne, Kyle Neath for sharing their thoughts with me on this!",2014,Jina Anne,jina,2014-12-19T00:00:00+00:00,https://24ways.org/2014/why-you-should-design-for-open-source/,design
197,Designing for Mobile Performance,"Last year, some colleagues at Google ran a research study titled “The Need for Mobile Speed” to find out what the impact of performance and perception of speed had on the way people use the web on their mobile devices.
That’s not a trivial distinction; when considering performance, how fast something feels is often more important than how fast it actually is. When dealing with sometimes underpowered mobile devices and slow mobile networks, designing experiences that feel fast is exceptionally important.
One of the most startling numbers we found in the study was that 53% of mobile site visits are abandoned if pages take longer than 3 seconds to load.
We wanted to find out more, so following on from this study, we conducted research to define what the crucial elements of speed are. We took into consideration the user experience (UX), overall perception of speed, and how differing contexts the user finds themselves in can alter how fast a user thinks something loaded.
To understand speed and load times first we must understand that user mobile web behaviour is broken down into three buckets;
Intention
Location
State of mind
Let’s look at each of those in turn.
Intention
Users browse sites on a mobile device for many different reasons. To be able to effectively design a performant user experience for them, it’s important to understand what those reasons might be. When asked to describe their reason for visiting a site, approximately 30% of people asked by the study claimed that they were simply browsing without a particular purpose in mind. Looking deeper, we found that this number increased slightly (34%) for retail sites. 30% said they were just there to find out some information for a future task or action, such as booking a flight.
Interestingly, the research shows that users are actually window shopping using their mobile browser. Only 29% actually said they had a specific goal or intent in mind, and this number increases significantly for financial services like banking sites (57%). This goes against a traditionally held view of users wanting to perform simple actions efficiently on their mobile device. Sure, some users are absolutely doing that, but many are just browsing around without a goal in mind, just like they would on a desktop browser.
This gives great insight into the user’s intentions. It tells us that users are actively using sites on their mobile, but a large majority do not intend to do anything instantly. There’s no goal they’re under pressure to achieve. If a site’s performance is lousy or janky, this will only reaffirm to the user to that they can hold off on completing a task, so they might just give up.
However, if a site is quick to load, sophisticated in expressing its value proposition quickly, and enables the user to perform their actions seamlessly, then turning that “browsing user” into a “buying user” becomes all that much easier. When the user has no goal, there’s more opportunity to convert, and you stand a greater chance of doing that if the performance is good enough so they stick around.
Location
Obviously, mobile devices by their nature can be used in many different locations. This is an interesting consideration, because it’s not something we traditionally need to take into account designing experiences for static platforms like desktop computers.
The in the study, we found that 82% of users browse the web on their mobile phone while in their home. In contrast, only 7% do the same while at work. This might come across as a bit of a shock, but when you look at mobile usage – in particular app usage – most of the apps being used are either a social network or some sort of entertainment or media app. Due to the unreliability of network connections, users will often alternate between these two types of apps.
The consequence being that if a site doesn’t work offline, or otherwise compensate for bad network connectivity in some way by providing opportunities to allow users to browse their site, then it becomes a self-fulfilling prophecy as to why users mostly view the mobile web from the comfort of their homes where there is a strong WiFi connection. They’re using mobile devices, but they’re not actually mobile themselves.
Another thing to bear in mind is how users alternate between devices, a study by comScore found that 80% of transactions take place on desktop while 69% of the browsing takes place on mobile. Any given user might access from more than one location - they might visit one day from a bus queue on their phone, and then next day from a laptop at home.
State of mind
One more thing we need to take into consideration is the user’s state of mind. Whilst browsing at home, users tend to be more relaxed, and in the research 76% stated they were generally calmer at home. The user’s state of mind can have quite a big impact on how they perceive things. The calmer they are, the quicker a site might appear to load. If the user is anxious and impatiently drumming their fingers on the table, things seem to take longer, and even a small wait can feel like an eternity.
This is quite key. Over 40% of sites take longer than 4 seconds to load for users who are are out and about and using a mobile data connection. Coupled with our perception, and amplified by a potentially less-than-calm state of mind, this can seem like an age.
What does this all mean?
I think we can all agree that users prefer strong, steady connections and comfort when completing transactions. It seems like common sense when we say it out loud. Recreating these feelings and sensations of comfort and predictability under all circumstances therefore becomes paramount. Equally, when asked in the study, users all claimed that speed was the most important factor impacting their mobile web usage. Over 40%, in fact, said it was the most important UX feature of a site, and nobody asked considered it to be of no importance at all.
The meaning of speed
When it comes to performance, speed is measured in two ways – real speed; as measured on a clock, and perceived speed; how responsive an interaction feels. We can, of course, improve how quickly a site loads by simply making files smaller. Even then, the study showed that 32% of users felt a site can feel slow even when it loads in less than 4 seconds. This gets even worse when you look at it by age group, with 50% if young people (18-24 year olds) thinking a site was slower than it actually was. When you add to the mix that users think a site loaded faster when they are sitting compared to when they are standing up, then you are in a world of trouble if your site doesn’t have any clear indicators to let the user know the loading state of you website or app.
So what can we do about this to improve our designs?
How to fix / hack user perception
There are some golden rules of speed, the first thing is hacking response time. If a page takes more than 3 seconds to load, you will certainly start to lose your users. However, if that slowness is part of a UX flow such as processing information, the user understands it might take a little time. Under those circumstances, a load time of under 5 seconds is acceptable, but even then, you should take caution. Anything above 8 seconds and you are in very real danger of losing your audience completely.
Load time
User impression
200 ms
Feels instant
1 s
Feels it is performing smoothly
5 s
Part of user flow
8 s
Lose attention
Remove the tap delay
Mobile browsers often use a 300-350ms delay between the triggering of the touchend and click events. This delay was added so the browser could determine if there was going to be a double-tap triggered or not, since double-tap is a common gesture used to zoom into text. This delay can have the side effect of making interactions feel laggy, and therefore giving the user the impression that the site is slow, even if it’s their own browser causing the problem.
Fortunately there’s a way to remove the delay. Add following in the of your page, and the delay no longer takes effect:
You can also use touch-action: manipulation in newer browsers to eliminate click delay. For old browsers, FastClick by FT Labs uses touch events to trigger clicks faster and remove the double-tap gesture.
Make use of Skeleton Screens
A skeleton layout is a wireframe version of your app that displays while content is being loaded. This demonstrates to the user that content is about to be loaded, giving the impression that something is happening more quickly than it really is. Consider also using a preloader UI as well, with a text label informing the user that the app is loading. One example would be to pulsate the wireframe content giving the app the feeling that it is alive and loading. This reassures the user that something is happening and helps prevent resubmissions or refreshes of your app. Razvan Caliman created a Codepen example of how to create this effect in purely CSS.
One thing to consider though, if data doesn’t load then you might need to create a fallback 404 or error page to let the user know what happened.
Example by Owen-Campbell Moore
Responsive Touch Feedback
Carefully designing the process by which items load is one aspect of increasing the perceived speed of your page, but reassuring the user that an action they have taken is in process is another. At Google we use something called a Ripple, which is is animating dot that expands or ripples in order to confirm to the user that their input has been triggered. This happens immediately, expanding outward from the point of touch. This reaffirms to the user that their input has been received and is being acted on, even before the site has had a chance to process or respond to the action. From the user’s point of view, they’ve tapped and the page has responded immediately, so it feels really quick and satisfying.
You can mimic this same behavior using our Material Design Components Web GitHub repo.
Progress bars
These UI elements have existed for a very long time, but research conducted by Chris Harrison and published in New Scientist found that the style of a progress bar can alter the perception of speed drastically. As a matter of fact, progress bars with ripples that animate towards the left appear like they are loading faster by at least 11% percent. So when including them in your site, take into consideration that ripples and progress bars that pulsate faster as they get to the end will make your sites seem quicker.
Faster Progress Bars: Manipulating Perceived Duration with Visual Augmentations
Navigation
The speed with which a user can locate navigational items or call to actions adds to their perceived performance of a site. If the user’s next action is quick to spot on the screen, they don’t spend time hunting around the interface with their eyes and fingers. So no matter how quickly your code runs, hiding items behind a nav bar will make a site feel slower than it actually is.
Facebook found that switching to using bottom navigation saw an increase in engagement, satisfaction, revenue, speed, and importantly, perception of speed. If the user sees the navigation items they’re looking for quickly, the interaction feels fast. What’s more, end-to-end task completion is quicker too, as the interface not only feels quicker, but actually measures quicker as well. Similar reactions were found with Spotify and Redbooth.
Luke Wroblewski gave a talk last year in Ireland titled “Obvious Always Wins” which he demonstrated through the work he did with Google+. Luke’s message is that by making the core features of your app obvious to your user, you will see engagement go up. This again seems obvious, right? However, it is important to note that adding bottom navigation doesn’t just mean a black bar at the bottom of your screen like some kind of performance magic bullet. The goal is to make the items clear to the user so they know what they need to be doing, and how you achieve that could be different from one interface to the next. Google keeps experimenting with different navigation styles, but finally settled with the below when they conducted user research and testing.
Conclusion
By utilizing a collection of UI patterns and speed optimisation techniques, you can improve not only the actual speed of a site, but the perception of how quickly a user thinks your site is loading. It is critical to remember that users will not always be using your site in a calm and relaxed manner and that even their age can impact how they will use or not use your site. By improving your site’s stability, you increase the likelihood of positive user engagement and task completion.
You can learn more about techniques to hack user perception and improve user speed by taking a look at an E-Book we published with Awwwards.com called Speed Matters: Design for Mobile Performance.",2017,Mustafa Kurtuldu,mustafakurtuldu,2017-12-18T00:00:00+00:00,https://24ways.org/2017/designing-for-mobile-performance/,ux
234,An Introduction to CSS 3-D Transforms,"Ladies and gentlemen, it is the second decade of the third millennium and we are still kicking around the same 2-D interface we got three decades ago. Sure, Apple debuted a few apps for OSX 10.7 that have a couple more 3-D flourishes, and Microsoft has had that Flip 3D for a while. But c’mon – 2011 is right around the corner. That’s Twenty Eleven, folks. Where is our 3-D virtual reality? By now, we should be zipping around the Metaverse on super-sonic motorbikes.
Granted, the capability of rendering complex 3-D environments has been present for years. On the web, there are already several solutions: Flash; three.js in ; and, eventually, WebGL. Finally, we meagre front-end developers have our own three-dimensional jewel: CSS 3-D transforms!
Rationale
Like a beautiful jewel, 3-D transforms can be dazzling, a true spectacle to behold. But before we start tacking 3-D diamonds and rubies to our compositions like Liberace‘s tailor, we owe it to our users to ask how they can benefit from this awesome feature.
An entire application should not take advantage of 3-D transforms. CSS was built to style documents, not generate explorable environments. I fail to find a benefit to completing a web form that can be accessed by swivelling my viewport to the Sign-Up Room (although there have been proposals to make the web just that). Nevertheless, there are plenty of opportunities to use 3-D transforms in between interactions with the interface, via transitions.
Take, for instance, the Weather App on the iPhone. The application uses two views: a details view; and an options view. Switching between these two views is done with a 3-D flip transition. This informs the user that the interface has two – and only two – views, as they can exist only on either side of the same plane.
Flipping from details view to options view via a 3-D transition
Also, consider slide shows. When you’re looking at the last slide, what cues tip you off that advancing will restart the cycle at the first slide? A better paradigm might be achieved with a 3-D transform, placing the slides side-by-side in a circle (carousel) in three-dimensional space; in that arrangement, the last slide obviously comes before the first.
3-D transforms are more than just eye candy. We can also use them to solve dilemmas and make our applications more intuitive.
Current support
The CSS 3D Transforms module has been out in the wild for over a year now. Currently, only Safari supports the specification – which includes Safari on Mac OS X and Mobile Safari on iOS.
The support roadmap for other browsers varies. The Mozilla team has taken some initial steps towards implementing the module. Mike Taylor tells me that the Opera team is keeping a close eye on CSS transforms, and is waiting until the specification is fleshed out. And our best friend Internet Explorer still needs to catch up to 2-D transforms before we can talk about the 3-D variety.
To make matters more perplexing, Safari’s WebKit cousin Chrome currently accepts 3-D transform declarations, but renders them in 2-D space. Chrome team member Paul Irish, says that 3-D transforms are on the horizon, perhaps in one of the next 8.0 releases.
This all adds up to a bit of a challenge for those of us excited by 3-D transforms. I’ll give it to you straight: missing the dimension of depth can make degradation a bit ungraceful. Unless the transform is relatively simple and holds up in non-3D-supporting browsers, you’ll most likely have to design another solution. But what’s another hurdle in a steeplechase? We web folk have had our mettle tested for years. We’re prepared to devise multiple solutions.
Here’s the part of the article where I mention Modernizr, and you brush over it because you’ve read this part of an article hundreds of times before. But seriously, it’s the best way to test for CSS 3-D transform support. Use it.
Even with these difficulties mounting up, trying out 3-D transforms today is the right move. The CSS 3-D transforms module was developed by the same team at Apple that produced the CSS 2D Transforms and Animation modules. Both specifications have since been adopted by Mozilla and Opera. Transforming in three-dimensions now will guarantee you’ll be ahead of the game when the other browsers catch up.
The choice is yours. You can make excuses and pooh-pooh 3-D transforms because they’re too hard and only snobby Apple fans will see them today. Or, with a tip of the fedora to Mr Andy Clarke, you can get hard-boiled and start designing with the best features out there right this instant.
So, I bid you, in the words of the eternal Optimus Prime…
Transform and roll out.
Let’s get coding.
Perspective
To activate 3-D space, an element needs perspective. This can be applied in two ways: using the transform property, with the perspective as a functional notation:
-webkit-transform: perspective(600);
or using the perspective property:
-webkit-perspective: 600;
See example: Perspective 1.
The red element on the left uses transform: perspective() functional notation; the blue element on the right uses the perspective property
These two formats both trigger a 3-D space, but there is a difference. The first, functional notation is convenient for directly applying a 3-D transform on a single element (in the previous example, I use it in conjunction with a rotateY transform). But when used on multiple elements, the transformed elements don’t line up as expected. If you use the same transform across elements with different positions, each element will have its own vanishing point. To remedy this, use the perspective property on a parent element, so each child shares the same 3-D space.
See Example: Perspective 2.
Each red box on the left has its own vanishing point within the parent container; the blue boxes on the right share the vanishing point of the parent container
The value of perspective determines the intensity of the 3-D effect. Think of it as a distance from the viewer to the object. The greater the value, the further the distance, so the less intense the visual effect. perspective: 2000; yields a subtle 3-D effect, as if we were viewing an object from far away. perspective: 100; produces a tremendous 3-D effect, like a tiny insect viewing a massive object.
By default, the vanishing point for a 3-D space is positioned at its centre. You can change the position of the vanishing point with perspective-origin property.
-webkit-perspective-origin: 25% 75%;
See Example: Perspective 3.
3-D transform functions
As a web designer, you’re probably well acquainted with working in two dimensions, X and Y, positioning items horizontally and vertically. With a 3-D space initialised with perspective, we can now transform elements in all three glorious spatial dimensions, including the third Z dimension, depth.
3-D transforms use the same transform property used for 2-D transforms. If you’re familiar with 2-D transforms, you’ll find the basic 3D transform functions fairly similar.
rotateX(angle)
rotateY(angle)
rotateZ(angle)
translateZ(tz)
scaleZ(sz)
Whereas translateX() positions an element along the horizontal X-axis, translateZ() positions it along the Z-axis, which runs front to back in 3-D space. Positive values position the element closer to the viewer, negative values further away.
The rotate functions rotate the element around the corresponding axis. This is somewhat counter-intuitive at first, as you might imagine that rotateX will spin an object left to right. Instead, using rotateX(45deg) rotates an element around the horizontal X-axis, so the top of the element angles back and away, and the bottom gets closer to the viewer.
See Example: Transforms 1.
3-D rotate() and translate() functions around each axis
There are also several shorthand transform functions that require values for all three dimensions:
translate3d(tx,ty,tz)
scale3d(sx,sy,sz)
rotate3d(rx,ry,rz,angle)
Pro-tip: These foo3d() transform functions also have the benefit of triggering hardware acceleration in Safari. Dean Jackson, CSS 3-D transform spec author and main WebKit dude, writes (to Thomas Fuchs):
In essence, any transform that has a 3D operation as one of its functions will trigger hardware compositing, even when the actual transform is 2D, or not doing anything at all (such as translate3d(0,0,0)). Note this is just current behaviour, and could change in the future (which is why we don’t document or encourage it). But it is very helpful in some situations and can significantly improve redraw performance.
For the sake of simplicity, my demos will use the basic transform functions, but if you’re writing production-ready CSS for iOS or Safari-only, make sure to use the foo3d() functions to get the best rendering performance.
Card flip
We now have all the tools to start making 3-D objects. Let’s get started with something simple: flipping a card.
Here’s the basic markup we’ll need:
The .container will house the 3-D space. The #card acts as a wrapper for the 3-D object. Each face of the card has a separate element: .front; and .back. Even for such a simple object, I recommend using this same pattern for any 3-D transform. Keeping the 3-D space element and the object element(s) separate establishes a pattern that is simple to understand and easier to style.
We’re ready for some 3-D stylin’. First, apply the necessary perspective to the parent 3-D space, along with any size or positioning styles.
.container {
width: 200px;
height: 260px;
position: relative;
-webkit-perspective: 800;
}
Now the #card element can be transformed in its parent’s 3-D space. We’re combining absolute and relative positioning so the 3-D object is removed from the flow of the document. We’ll also add width: 100%; and height: 100%;. This ensures the object’s transform-origin will occur in the centre of .container. More on transform-origin later.
Let’s add a CSS3 transition so users can see the transform take effect.
#card {
width: 100%;
height: 100%;
position: absolute;
-webkit-transform-style: preserve-3d;
-webkit-transition: -webkit-transform 1s;
}
The .container’s perspective only applies to direct descendant children, in this case #card. In order for subsequent children to inherit a parent’s perspective, and live in the same 3-D space, the parent can pass along its perspective with transform-style: preserve-3d. Without 3-D transform-style, the faces of the card would be flattened with its parents and the back face’s rotation would be nullified.
To position the faces in 3-D space, we’ll need to reset their positions in 2-D with position: absolute. In order to hide the reverse sides of the faces when they are faced away from the viewer, we use backface-visibility: hidden.
#card figure {
display: block;
position: absolute;
width: 100%;
height: 100%;
-webkit-backface-visibility: hidden;
}
To flip the .back face, we add a basic 3-D transform of rotateY(180deg).
#card .front {
background: red;
}
#card .back {
background: blue;
-webkit-transform: rotateY(180deg);
}
With the faces in place, the #card requires a corresponding style for when it is flipped.
#card.flipped {
-webkit-transform: rotateY(180deg);
}
Now we have a working 3-D object. To flip the card, we can toggle the flipped class. When .flipped, the #card will rotate 180 degrees, thus exposing the .back face.
See Example: Card 1.
Flipping a card in three dimensions
Slide-flip
Take another look at the Weather App 3-D transition. You’ll notice that it’s not quite the same effect as our previous demo. If you follow the right edge of the card, you’ll find that its corners stay within the container. Instead of pivoting from the horizontal centre, it pivots on that right edge. But the transition is not just a rotation – the edge moves horizontally from right to left. We can reproduce this transition just by modifying a couple of lines of CSS from our original card flip demo.
The pivot point for the rotation occurs at the right side of the card. By default, the transform-origin of an element is at its horizontal and vertical centre (50% 50% or center center). Let’s change it to the right side:
#card { -webkit-transform-origin: right center; }
That flip now needs some horizontal movement with translateX. We’ll set the rotation to -180deg so it flips right side out.
#card.flipped {
-webkit-transform: translateX(-100%) rotateY(-180deg);
}
See Example: Card 2.
Creating a slide-flip from the right edge of the card
Cube
Creating 3-D card objects is a good way to get started with 3-D transforms. But once you’ve mastered them, you’ll be hungry to push it further and create some true 3-D objects: prisms. We’ll start out by making a cube.
The markup for the cube is similar to the card. This time, however, we need six child elements for all six faces of the cube:
Basic position and size styles set the six faces on top of one another in the container.
.container {
width: 200px;
height: 200px;
position: relative;
-webkit-perspective: 1000;
}
#cube {
width: 100%;
height: 100%;
position: absolute;
-webkit-transform-style: preserve-3d;
}
#cube figure {
width: 196px;
height: 196px;
display: block;
position: absolute;
border: 2px solid black;
}
With the card, we only had to rotate its back face. The cube, however, requires that five of the six faces to be rotated. Faces 1 and 2 will be the front and back. Faces 3 and 4 will be the sides. Faces 5 and 6 will be the top and bottom.
#cube .front { -webkit-transform: rotateY(0deg); }
#cube .back { -webkit-transform: rotateX(180deg); }
#cube .right { -webkit-transform: rotateY(90deg); }
#cube .left { -webkit-transform: rotateY(-90deg); }
#cube .top { -webkit-transform: rotateX(90deg); }
#cube .bottom { -webkit-transform: rotateX(-90deg); }
We could remove the first #cube .front style declaration, as this transform has no effect, but let’s leave it in to keep our code consistent.
Now each face is rotated, and only the front face is visible. The four side faces are all perpendicular to the viewer, so they appear invisible. To push them out to their appropriate sides, they need to be translated out from the centre of their positions. Each side of the cube is 200 pixels wide. From the cube’s centre they’ll need to be translated out half that distance, 100px.
#cube .front { -webkit-transform: rotateY(0deg) translateZ(100px); }
#cube .back { -webkit-transform: rotateX(180deg) translateZ(100px); }
#cube .right { -webkit-transform: rotateY(90deg) translateZ(100px); }
#cube .left { -webkit-transform: rotateY(-90deg) translateZ(100px); }
#cube .top { -webkit-transform: rotateX(90deg) translateZ(100px); }
#cube .bottom { -webkit-transform: rotateX(-90deg) translateZ(100px); }
Note here that the translateZ function comes after the rotate. The order of transform functions is important. Take a moment and soak this up. Each face is first rotated towards its position, then translated outward in a separate vector.
We have a working cube, but we’re not done yet.
Returning to the Z-axis origin
For the sake of our users, our 3-D transforms should not distort the interface when the active panel is at its resting position. But once we start pushing elements off their Z-axis origin, distortion is inevitable.
In order to keep 3-D transforms snappy, Safari composites the element, then applies the transform. Consequently, anti-aliasing on text will remain whatever it was before the transform was applied. When transformed forward in 3-D space, significant pixelation can occur.
See Example: Transforms 2.
Looking back at the Perspective 3 demo, note that no matter how small the perspective value is, or wherever the transform-origin may be, the panel number 1 always returns to its original position, as if all those funky 3-D transforms didn’t even matter.
To resolve the distortion and restore pixel perfection to our #cube, we can push the 3-D object back, so that the front face will be positioned back to the Z-axis origin.
#cube { -webkit-transform: translateZ(-100px); }
See Example: Cube 1.
Restoring the front face to the original position on the Z-axis
Rotating the cube
To expose any face of the cube, we’ll need a style that rotates the cube to expose any face. The transform values are the opposite of those for the corresponding face. We toggle the necessary class on the #box to apply the appropriate transform.
#cube.show-front { -webkit-transform: translateZ(-100px) rotateY(0deg); }
#cube.show-back { -webkit-transform: translateZ(-100px) rotateX(-180deg); }
#cube.show-right { -webkit-transform: translateZ(-100px) rotateY(-90deg); }
#cube.show-left { -webkit-transform: translateZ(-100px) rotateY(90deg); }
#cube.show-top { -webkit-transform: translateZ(-100px) rotateX(-90deg); }
#cube.show-bottom { -webkit-transform: translateZ(-100px) rotateX(90deg); }
Notice how the order of the transform functions has reversed. First, we push the object back with translateZ, then we rotate it.
Finishing up, we can add a transition to animate the rotation between states.
#cube { -webkit-transition: -webkit-transform 1s; }
See Example: Cube 2.
Rotating the cube with a CSS transition
Rectangular prism
Cubes are easy enough to generate, as we only have to worry about one measurement. But how would we handle a non-regular rectangular prism? Let’s try to make one that’s 300 pixels wide, 200 pixels high, and 100 pixels deep.
The markup remains the same as the #cube, but we’ll switch the cube id for #box. The container styles remain mostly the same:
.container {
width: 300px;
height: 200px;
position: relative;
-webkit-perspective: 1000;
}
#box {
width: 100%;
height: 100%;
position: absolute;
-webkit-transform-style: preserve-3d;
}
Now to position the faces. Each set of faces will need their own sizes. The smaller faces (left, right, top and bottom) need to be positioned in the centre of the container, where they can be easily rotated and then shifted outward. The thinner left and right faces get positioned left: 100px ((300 − 100) ÷ 2), The stouter top and bottom faces get positioned top: 50px ((200 − 100) ÷ 2).
#box figure {
display: block;
position: absolute;
border: 2px solid black;
}
#box .front,
#box .back {
width: 296px;
height: 196px;
}
#box .right,
#box .left {
width: 96px;
height: 196px;
left: 100px;
}
#box .top,
#box .bottom {
width: 296px;
height: 96px;
top: 50px;
}
The rotate values can all remain the same as the cube example, but for this rectangular prism, the translate values do differ. The front and back faces are each shifted out 50 pixels since the #box is 100 pixels deep. The translate value for the left and right faces is 150 pixels for their 300 pixels width. Top and bottom panels take 100 pixels for their 200 pixels height:
#box .front { -webkit-transform: rotateY(0deg) translateZ(50px); }
#box .back { -webkit-transform: rotateX(180deg) translateZ(50px); }
#box .right { -webkit-transform: rotateY(90deg) translateZ(150px); }
#box .left { -webkit-transform: rotateY(-90deg) translateZ(150px); }
#box .top { -webkit-transform: rotateX(90deg) translateZ(100px); }
#box .bottom { -webkit-transform: rotateX(-90deg) translateZ(100px); }
See Example: Box 1.
Just like the cube example, to expose a face, the #box needs to have a style to reverse that face’s transform. Both the translateZ and rotate values are the opposites of the corresponding face.
#box.show-front { -webkit-transform: translateZ(-50px) rotateY(0deg); }
#box.show-back { -webkit-transform: translateZ(-50px) rotateX(-180deg); }
#box.show-right { -webkit-transform: translateZ(-150px) rotateY(-90deg); }
#box.show-left { -webkit-transform: translateZ(-150px) rotateY(90deg); }
#box.show-top { -webkit-transform: translateZ(-100px) rotateX(-90deg); }
#box.show-bottom { -webkit-transform: translateZ(-100px) rotateX(90deg); }
See Example: Box 2.
Rotating the rectangular box with a CSS transition
Carousel
Front-end developers have a myriad of choices when it comes to content carousels. Now that we have 3-D capabilities in our browsers, why not take a shot at creating an actual 3-D carousel?
The markup for this demo takes the same form as the box, cube and card. Let’s make it interesting and have a carousel with nine panels.
Now, apply basic layout styles. Let’s give each panel of the #carousel 20 pixel gaps between one another, done here with left: 10px; and top: 10px;. The effective width of each panel is 210 pixels.
.container {
width: 210px;
height: 140px;
position: relative;
-webkit-perspective: 1000;
}
#carousel {
width: 100%;
height: 100%;
position: absolute;
-webkit-transform-style: preserve-3d;
}
#carousel figure {
display: block;
position: absolute;
width: 186px;
height: 116px;
left: 10px;
top: 10px;
border: 2px solid black;
}
Next up: rotating the faces. This #carousel has nine panels. If each panel gets an equal distribution on the carousel, each panel would be rotated forty degrees from its neighbour (360 ÷ 9).
#carousel figure:nth-child(1) { -webkit-transform: rotateY(0deg); }
#carousel figure:nth-child(2) { -webkit-transform: rotateY(40deg); }
#carousel figure:nth-child(3) { -webkit-transform: rotateY(80deg); }
#carousel figure:nth-child(4) { -webkit-transform: rotateY(120deg); }
#carousel figure:nth-child(5) { -webkit-transform: rotateY(160deg); }
#carousel figure:nth-child(6) { -webkit-transform: rotateY(200deg); }
#carousel figure:nth-child(7) { -webkit-transform: rotateY(240deg); }
#carousel figure:nth-child(8) { -webkit-transform: rotateY(280deg); }
#carousel figure:nth-child(9) { -webkit-transform: rotateY(320deg); }
Now, the outward shift. Back when we were creating the cube and box, the translate value was simple to calculate, as it was equal to one half the width, height or depth of the object. With this carousel, there is no size we can automatically use as a reference. We’ll have to calculate the distance of the shift by other means.
Drawing a diagram of the carousel, we can see that we know only two things: the width of each panel is 210 pixels; and the each panel is rotated forty degrees from the next. If we split one of these segments down its centre, we get a right-angled triangle, perfect for some trigonometry.
We can determine the length of r in this diagram with a basic tangent equation:
There you have it: the panels need to be translated 288 pixels in 3-D space.
#carousel figure:nth-child(1) { -webkit-transform: rotateY(0deg) translateZ(288px); }
#carousel figure:nth-child(2) { -webkit-transform: rotateY(40deg) translateZ(288px); }
#carousel figure:nth-child(3) { -webkit-transform: rotateY(80deg) translateZ(288px); }
#carousel figure:nth-child(4) { -webkit-transform: rotateY(120deg) translateZ(288px); }
#carousel figure:nth-child(5) { -webkit-transform: rotateY(160deg) translateZ(288px); }
#carousel figure:nth-child(6) { -webkit-transform: rotateY(200deg) translateZ(288px); }
#carousel figure:nth-child(7) { -webkit-transform: rotateY(240deg) translateZ(288px); }
#carousel figure:nth-child(8) { -webkit-transform: rotateY(280deg) translateZ(288px); }
#carousel figure:nth-child(9) { -webkit-transform: rotateY(320deg) translateZ(288px); }
If we decide to change the width of the panel or the number of panels, we only need to plug in those two variables into our equation to get the appropriate translateZ value. In JavaScript terms, that equation would be:
var tz = Math.round( ( panelSize / 2 ) /
Math.tan( ( ( Math.PI * 2 ) / numberOfPanels ) / 2 ) );
// or simplified to
var tz = Math.round( ( panelSize / 2 ) /
Math.tan( Math.PI / numberOfPanels ) );
Just like our previous 3-D objects, to show any one panel we need only apply the reverse transform on the carousel. Here’s the style to show the fifth panel:
-webkit-transform: translateZ(-288px) rotateY(-160deg);
See Example: Carousel 1.
By now, you probably have two thoughts:
Rewriting transform styles for each panel looks tedious.
Why bother doing high school maths? Aren’t robots supposed to be doing all this work for us?
And you’re absolutely right. The repetitive nature of 3-D objects lends itself to scripting. We can offload all the monotonous transform styles to our dynamic script, which, if done correctly, will be more flexible than the hard-coded version.
See Example: Carousel 2.
Conclusion
3-D transforms change the way we think about the blank canvas of web design. Better yet, they change the canvas itself, trading in the flat surface for voluminous depth.
My hope is that you took at least one peak at a demo and were intrigued. We web designers, who have rejoiced for border-radius, box-shadow and background gradients, now have an incredible tool at our disposal in 3-D transforms. They deserve just the same enthusiasm, research and experimentation we have seen on other CSS3 features. Now is the perfect time to take the plunge and start thinking about how to use three dimensions to elevate our craft. I’m breathless waiting for what’s to come.
See you on the flip side.",2010,David DeSandro,daviddesandro,2010-12-14T00:00:00+00:00,https://24ways.org/2010/intro-to-css-3d-transforms/,code
326,Don't be eval(),"JavaScript is an interpreted language, and like so many of its peers it includes the all powerful eval() function. eval() takes a string and executes it as if it were regular JavaScript code. It’s incredibly powerful and incredibly easy to abuse in ways that make your code slower and harder to maintain. As a general rule, if you’re using eval() there’s probably something wrong with your design.
Common mistakes
Here’s the classic misuse of eval(). You have a JavaScript object, foo, and you want to access a property on it – but you don’t know the name of the property until runtime. Here’s how NOT to do it:
var property = 'bar';
var value = eval('foo.' + property);
Yes it will work, but every time that piece of code runs JavaScript will have to kick back in to interpreter mode, slowing down your app. It’s also dirt ugly.
Here’s the right way of doing the above:
var property = 'bar';
var value = foo[property];
In JavaScript, square brackets act as an alternative to lookups using a dot. The only difference is that square bracket syntax expects a string.
Security issues
In any programming language you should be extremely cautious of executing code from an untrusted source. The same is true for JavaScript – you should be extremely cautious of running eval() against any code that may have been tampered with – for example, strings taken from the page query string. Executing untrusted code can leave you vulnerable to cross-site scripting attacks.
What’s it good for?
Some programmers say that eval() is B.A.D. – Broken As Designed – and should be removed from the language. However, there are some places in which it can dramatically simplify your code. A great example is for use with XMLHttpRequest, a component of the set of tools more popularly known as Ajax. XMLHttpRequest lets you make a call back to the server from JavaScript without refreshing the whole page. A simple way of using this is to have the server return JavaScript code which is then passed to eval(). Here is a simple function for doing exactly that – it takes the URL to some JavaScript code (or a server-side script that produces JavaScript) and loads and executes that code using XMLHttpRequest and eval().
function evalRequest(url) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState==4 && xmlhttp.status==200) {
eval(xmlhttp.responseText);
}
}
xmlhttp.open(""GET"", url, true);
xmlhttp.send(null);
}
If you want this to work with Internet Explorer you’ll need to include this compatibility patch.",2005,Simon Willison,simonwillison,2005-12-07T00:00:00+00:00,https://24ways.org/2005/dont-be-eval/,code
37,JavaScript Modules the ES6 Way,"JavaScript admittedly has plenty of flaws, but one of the largest and most prominent is the lack of a module system: a way to split up your application into a series of smaller files that can depend on each other to function correctly.
This is something nearly all other languages come with out of the box, whether it be Ruby’s require, Python’s import, or any other language you’re familiar with. Even CSS has @import! JavaScript has nothing of that sort, and this has caused problems for application developers as they go from working with small websites to full client-side applications. Let’s be clear: it doesn’t mean the new module system in the upcoming version of JavaScript won’t be useful to you if you’re building smaller websites rather than the next Instagram.
Thankfully, the lack of a module system will soon be a problem of the past. The next version of JavaScript, ECMAScript 6, will bring with it a full-featured module and dependency management solution for JavaScript. The bad news is that it won’t be landing in browsers for a while yet – but the good news is that the specification for the module system and how it will look has been finalised. The even better news is that there are tools available to get it all working in browsers today without too much hassle. In this post I’d like to give you the gift of JS modules and show you the syntax, and how to use them in browsers today. It’s much simpler than you might think.
What is ES6?
ECMAScript is a scripting language that is standardised by a company called Ecma International. JavaScript is an implementation of ECMAScript. ECMAScript 6 is simply the next version of the ECMAScript standard and, hence, the next version of JavaScript. The spec aims to be fully comfirmed and complete by the end of 2014, with a target initial release date of June 2015. It’s impossible to know when we will have full feature support across the most popular browsers, but already some ES6 features are landing in the latest builds of Chrome and Firefox. You shouldn’t expect to be able to use the new features across browsers without some form of additional tooling or library for a while yet.
The ES6 module spec
The ES6 module spec was fully confirmed in July 2014, so all the syntax I will show you in this article is not expected to change. I’ll first show you the syntax and the new APIs being added to the language, and then look at how to use them today. There are two parts to the new module system. The first is the syntax for declaring modules and dependencies in your JS files, and the second is a programmatic API for loading in modules manually. The first is what most people are expected to use most of the time, so it’s what I’ll focus on more.
Module syntax
The key thing to understand here is that modules have two key components. First, they have dependencies. These are things that the module you are writing depends on to function correctly. For example, if you were building a carousel module that used jQuery, you would say that jQuery is a dependency of your carousel. You import these dependencies into your module, and we’ll see how to do that in a minute. Second, modules have exports. These are the functions or variables that your module exposes publicly to anything that imports it. Using jQuery as the example again, you could say that jQuery exports the $ function. Modules that depend on and hence import jQuery get access to the $ function, because jQuery exports it.
Another important thing to note is that when I discuss a module, all I really mean is a JavaScript file. There’s no extra syntax to use other than the new ES6 syntax. Once ES6 lands, modules and files will be analogous.
Named exports
Modules can export multiple objects, which can be either plain old variables or JavaScript functions. You denote something to be exported with the export keyword:
export function double(x) {
return x + x;
};
You can also store something in a variable then export it. If you do that, you have to wrap the variable in a set of curly braces.
var double = function(x) {
return x + x;
}
export { double };
A module can then import the double function like so:
import { double } from 'mymodule';
double(2); // 4
Again, curly braces are required around the variable you would like to import. It’s also important to note that from 'mymodule' will look for a file called mymodule.js in the same directory as the file you are requesting the import from. There is no need to add the .js extension.
The reason for those extra braces is that this syntax lets you export multiple variables:
var double = function(x) {
return x + x;
}
var square = function(x) {
return x * x;
}
export { double, square }
I personally prefer this syntax over the export function …, but only because it makes it much clearer to me what the module exports. Typically I will have my export {…} line at the bottom of the file, which means I can quickly look in one place to determine what the module is exporting.
A file importing both double and square can do so in just the way you’d expect:
import { double, square } from 'mymodule';
double(2); // 4
square(3); // 9
With this approach you can’t easily import an entire module and all its methods. This is by design – it’s much better and you’re encouraged to import just the functions you need to use.
Default exports
Along with named exports, the system also lets a module have a default export. This is useful when you are working with a large library such as jQuery, Underscore, Backbone and others, and just want to import the entire library. A module can define its default export (it can only ever have one default export) like so:
export default function(x) {
return x + x;
}
And that can be imported:
import double from 'mymodule';
double(2); // 4
This time you do not use the curly braces around the name of the object you are importing. Also notice how you can name the import whatever you’d like. Default exports are not named, so you can import them as anything you like:
import christmas from 'mymodule';
christmas(2); // 4
The above is entirely valid.
Although it’s not something that is used too often, a module can have both named exports and a default export, if you wish.
One of the design goals of the ES6 modules spec was to favour default exports. There are many reasons behind this, and there is a very detailed discussion on the ES Discuss site about it. That said, if you find yourself preferring named exports, that’s fine, and you shouldn’t change that to meet the preferences of those designing the spec.
Programmatic API
Along with the syntax above, there is also a new API being added to the language so you can programmatically import modules. It’s pretty rare you would use this, but one obvious example is loading a module conditionally based on some variable or property. You could easily import a polyfill, for example, if the user’s browser didn’t support a feature your app relied on. An example of doing this is:
if(someFeatureNotSupported) {
System.import('my-polyfill').then(function(myPolyFill) {
// use the module from here
});
}
System.import will return a promise, which, if you’re not familiar, you can read about in this excellent article on HTMl5 Rocks by Jake Archibald. A promise basically lets you attach callback functions that are run when the asynchronous operation (in this case, System.import), is complete.
This programmatic API opens up a lot of possibilities and will also provide hooks to allow you to register callbacks that will run at certain points in the lifetime of a module. Those hooks and that syntax are slightly less set in stone, but when they are confirmed they will provide really useful functionality. For example, you could write code that would run every module that you import through something like JSHint before importing it. In development that would provide you with an easy way to keep your code quality high without having to run a command line watch task.
How to use it today
It’s all well and good having this new syntax, but right now it won’t work in any browser – and it’s not likely to for a long time. Maybe in next year’s 24 ways there will be an article on how you can use ES6 modules with no extra work in the browser, but for now we’re stuck with a bit of extra work.
ES6 module transpiler
One solution is to use the ES6 module transpiler, a compiler that lets you write your JavaScript using the ES6 module syntax (actually a subset of it – not quite everything is supported, but the main features are) and have it compiled into either CommonJS-style code (CommonJS is the module specification that NodeJS and Browserify use), or into AMD-style code (the spec RequireJS uses). There are also plugins for all the popular build tools, including Grunt and Gulp.
The advantage of using this transpiler is that if you are already using a tool like RequireJS or Browserify, you can drop the transpiler in, start writing in ES6 and not worry about any additional work to make the code work in the browser, because you should already have that set up already. If you don’t have any system in place for handling modules in the browser, using the transpiler doesn’t really make sense. Remember, all this does is convert ES6 module code into CommonJS- or AMD-compliant JavaScript. It doesn’t do anything to help you get that code running in the browser, but if you have that part sorted it’s a really nice addition to your workflow. If you would like a tutorial on how to do this, I wrote a post back in June 2014 on using ES6 with the ES6 module transpiler.
SystemJS
Another solution is SystemJS. It’s the best solution in my opinion, particularly if you are starting a new project from scratch, or want to use ES6 modules on a project where you have no current module system in place. SystemJS is a spec-compliant universal module loader: it loads ES6 modules, AMD modules, CommonJS modules, as well as modules that just add a variable to the global scope (window, in the browser).
To load in ES6 files, SystemJS also depends on two other libraries: the ES6 module loader polyfill; and Traceur. Traceur is best accessed through the bower-traceur package, as the main repository doesn’t have an easy to find downloadable version. The ES6 module load polyfill implements System.import, and lets you load in files using it. Traceur is an ES6-to-ES5 module loader. It takes code written in ES6, the newest version of JavaScript, and transpiles it into ES5, the version of JavaScript widely implemented in browsers. The advantage of this is that you can play with the new features of the language today, even though they are not supported in browsers. The drawback is that you have to run all your files through Traceur every time you save them, but this is easily automated. Additionally, if you use SystemJS, the Traceur compilation is done automatically for you.
All you need to do to get SystemJS running is to add a
When you load the page, app.js will be asynchronously loaded. Within app.js, you can now use ES6 modules. SystemJS will detect that the file is an ES6 file, automatically load Traceur, and compile the file into ES5 so that it works in the browser. It does all this dynamically in the browser, but there are tools to bundle your application in production, so it doesn’t make a lot of requests on the live site. In development though, it makes for a really nice workflow.
When working with SystemJS and modules in general, the best approach is to have a main module (in our case app.js) that is the main entry point for your application. app.js should then be responsible for loading all your application’s modules. This forces you to keep your application organised by only loading one file initially, and having the rest dealt with by that file.
SystemJS also provides a workflow for bundling your application together into one file.
Conclusion
ES6 modules may be at least six months to a year away (if not more) but that doesn’t mean they can’t be used today. Although there is an overhead to using them now – with the work required to set up SystemJS, the module transpiler, or another solution – that doesn’t mean it’s not worthwhile. Using any module system in the browser, whether that be RequireJS, Browserify or another alternative, requires extra tooling and libraries to support it, and I would argue that the effort to set up SystemJS is no greater than that required to configure any other tool. It also comes with the extra benefit that when the syntax is supported in browsers, you get a free upgrade. You’ll be able to remove SystemJS and have everything continue to work, backed by the native browser solution.
If you are starting a new project, I would strongly advocate using ES6 modules. It is a syntax and specification that is not going away at all, and will soon be supported in browsers. Investing time in learning it now will pay off hugely further down the road.
Further reading
If you’d like to delve further into ES6 modules (or ES6 generally) and using them today, I recommend the following resources:
ECMAScript 6 modules: the final syntax by Axel Rauschmayer
Practical Workflows for ES6 Modules by Guy Bedford
ECMAScript 6 resources for the curious JavaScripter by Addy Osmani
Tracking ES6 support by Addy Osmani
ES6 Tools List by Addy Osmani
Using Grunt and the ES6 Module Transpiler by Thomas Boyt
JavaScript Modules and Dependencies with jspm by myself
Using ES6 Modules Today by Guy Bedford",2014,Jack Franklin,jackfranklin,2014-12-03T00:00:00+00:00,https://24ways.org/2014/javascript-modules-the-es6-way/,code
193,Web Content Accessibility Guidelines—for People Who Haven't Read Them,"I’ve been a huge fan of the Web Content Accessibility Guidelines 2.0 since the World Wide Web Consortium (W3C) published them, nine years ago. I’ve found them practical and future-proof, and I’ve found that they can save a huge amount of time for designers and developers. You can apply them to anything that you can open in a browser. My favourite part is when I use the guidelines to make a website accessible, and then attend user-testing and see someone with a disability easily using that website.
Today, the United Nations International Day of Persons with Disabilities, seems like a good time to re-read Laura Kalbag’s explanation of why we should bother with accessibility. That should motivate you to devour this article.
If you haven’t read the Web Content Accessibility Guidelines 2.0, you might find them a bit off-putting at first. The editors needed to create a single standard that countries around the world could refer to in legislation, and so some of the language in the guidelines reads like legalese. The editors also needed to future-proof the guidelines, and so some terminology—such as “time-based media” and “programmatically determined”—can sound ambiguous. The guidelines can seem lengthy, too: printing the guidelines, the Understanding WCAG 2.0 document, and the Techniques for WCAG 2.0 document would take 1,200 printed pages.
This festive season, let’s rip off that legalese and ambiguous terminology like wrapping paper, and see—in a single article—what gifts the Web Content Accessibility Guidelines 2.0 editors have bestowed upon us.
Can your users perceive the information on your website?
The first guideline has criteria that help you prevent your users from asking “What the **** is this thing here supposed to be?”
1.1.1 Text is the most accessible format for information. Screen readers—such as the “VoiceOver” setting on your iPhone or the “TalkBack” app on your Android phone—understand text better than any other format. The same applies for other assistive technology, such as translation apps and Braille displays. So, if you have anything on your webpage that’s not text, you must add some text that gives your user the same information. You probably know how to do this already; for example:
for images in webpages, put some alternative text in an alt attribute to tell your user what the image conveys to the user;
for photos in tweets, add a description to make the images accessible;
for Instagram posts, write a caption that conveys the photo’s information.
The alternative text should allow the user to get the same information as someone who can see the image. For websites that have too many images for someone to add alternative text to, consider how machine learning and Dynamically Generated Alt Text might—might—be appropriate.
You can probably think of a few exceptions where providing text to describe an image might not make sense. Remember I described these guidelines as “practical”? They cover all those exceptions:
User interface controls such as buttons and text inputs must have names or labels to tell your user what they do.
If your webpage has video or audio (more about these later on!), you must—at least—have text to tell the user what they are.
Maybe your webpage has a test where your user has to answer a question about an image or some audio, and alternative text would give away the answer. In that case, just describe the test in text so your users know what it is.
If your webpage features a work of art, tell your user the experience it evokes.
If you have to include a Captcha on your webpage—and please avoid Captchas if at all possible, because some users cannot get past them—you must include text to tell your user what it is, and make sure that it doesn’t rely on only one sense, such as vision.
If you’ve included something just as decoration, you must make sure that your user’s assistive technology can ignore it. Again, you probably know how to do this. For example, you could use CSS instead of HTML to include decorative images, or you could add an empty alt attribute to the img element. (Please avoid that recent trend where developers add empty alt attributes to all images in a webpage just to make the HTML validate. You’re better than that.)
(Notice that the guidelines allow you to choose how to conform to them, with whatever technology you choose. To make your website conform to a guideline, you can either choose one of the techniques for WCAG 2.0 for that guideline or come up with your own. Choosing a tried-and-tested technique usually saves time!)
1.2.1 If your website includes a podcast episode, speech, lecture, or any other recorded audio without video, you must include a transcription or some other text to give your user the same information. In a lot of cases, you might find this easier than you expect: professional transcription services can prove relatively inexpensive and fast, and sometimes a speaker or lecturer can provide the speech or lecture notes that they read out word-for-word. Just make sure that all your users can get the same information and the same results, whether they can hear the audio or not. For example, David Smith and Marco Arment always publish episode transcripts for their Under the Radar podcast.
Similarly, if your website includes recorded video without audio—such as an animation or a promotional video—you must either use text to detail what happens in the video or include an audio version. Again, this might work out easier then you perhaps fear: for example, you could check to see whether the animation started life as a list of instructions, or whether the promotional video conveys the same information as the “About Us” webpage. You want to make sure that all your users can get the same information and the same results, whether they can see that video or not.
1.2.2 If your website includes recorded videos with audio, you must add captions to those videos for users who can’t hear the audio. Professional transcription services can provide you with time-stamped text in caption formats that YouTube supports, such as .srt and .sbv. You can upload those to YouTube, so captions appear on your videos there. YouTube can auto-generate captions, but the quality varies from impressively accurate to comically inaccurate. If you have a text version of what the people in the video said—such as the speech that a politician read or the bedtime story that an actor read—you can create a transcript file in .txt format, without timestamps. YouTube then creates captions for your video by synchronising that text to the audio in the video. If you host your own videos, you can ask a professional transcription service to give you .vtt files that you can add to a video element’s track element—or you can handcraft your own. (A quick aside: if your website has more videos than you can caption in a reasonable amount of time, prioritise the most popular videos, the most important videos, and the videos most relevant to people with disabilities. Then make sure your users know how to ask you to caption other videos as they encounter them.)
1.2.3 If your website has recorded videos that have audio, you must add an “audio description” narration to the video to describe important visual details, or add text to the webpage to detail what happens in the video for users who cannot see the videos. (I like to add audio files from videos to my Huffduffer account so that I can listen to them while commuting.) Maybe your home page has a video where someone says, “I’d like to explain our new TPS reports” while “Bill Lumbergh, division Vice President of Initech” appears on the bottom of the screen. In that case, you should add an audio description to the video that announces “Bill Lumbergh, division Vice President of Initech”, just before Bill starts speaking. As always, you can make life easier for yourself by considering all of your users, before the event: in this example, you could ask the speaker to begin by saying, “I’m Bill Lumbergh, division Vice President of Initech, and I’d like to explain our new TPS reports”—so you won’t need to spend time adding an audio description afterwards.
1.2.4 If your website has live videos that have some audio, you should get a stenographer to provide real-time captions that you can include with the video. I’ll be honest: this can prove tricky nowadays. The Web Content Accessibility Guidelines 2.0 predate YouTube Live, Instagram live Stories, Periscope, and other such services. If your organisation creates a lot of live videos, you might not have enough resources to provide real-time captions for each one. In that case, if you know the contents of the audio beforehand, publish the contents during the live video—or failing that, publish a transcription as soon as possible.
1.2.5 Remember what I said about the recorded videos that have audio? If you can choose to either add an audio description or add text to the webpage to detail what happens in the video, you should go with the audio description.
1.2.6 If your website has recorded videos that include audio information, you could provide a sign language version of the audio information; some people understand sign language better than written language. (You don’t need to caption a video of a sign language version of audio information.)
1.2.7 If your website has recorded videos that have audio, and you need to add an audio description, but the audio doesn’t have enough pauses for you to add an “audio description” narration, you could provide a separate version of that video where you have added pauses to fit the audio description into.
1.2.8 Let’s go back to the recorded videos that have audio once more! You could add text to the webpage to detail what happens in the video, so that people who can neither read captions nor hear dialogue and audio description can use braille displays to understand your video.
1.2.9 If your website has live audio, you could get a stenographer to provide real-time captions. Again, if you know the contents of the audio beforehand, publish the contents during the live audio or publish a transcription as soon as possible.
(Congratulations on making it this far! I know that seems like a lot to remember, but keep in mind that we’ve covered a complex area: helping your users to understand multimedia information that they can’t see and/or hear. Grab a mince pie to celebrate, and let’s keep going.)
1.3.1 You must mark up your website’s content so that your user’s browser, and any assistive technology they use, can understand the hierarchy of the information and how each piece of information relates to the rest. Once again, you probably know how to do this: use the most appropriate HTML element for each piece of information. Mark up headings, lists, buttons, radio buttons, checkboxes, and links with the most appropriate HTML element. If you’re looking for something to do to keep you busy this Christmas, scroll through the list of the elements of HTML. Do you notice any elements that you didn’t know, or that you’ve never used? Do you notice any elements that you could use on your current projects, to mark up the content more accurately? Also, revise HTML table advanced features and accessibility, how to structure an HTML form, and how to use the native form widgets—you might be surprised at how much you can do with just HTML! Once you’ve mastered those, you can make your website much more usable for your all of your users.
1.3.2 If your webpage includes information that your user has to read in a certain order, you must make sure that their browser and assistive technology can present the information in that order. Don’t rely on CSS or whitespace to create that order visually. Check that the order of the information makes sense when CSS and whitespace aren’t formatting it. Also, try using the Tab key to move the focus through the links and form widgets on your webpage. Does the focus go where you expect it to? Keep this in mind when using order in CSS Grid or Flexbox.
1.3.3 You must not presume that your users can identify sensory characteristics of things on your webpage. Some users can’t tell what you’ve positioned where on the screen. For example, instead of asking your users to “Choose one of the options on the left”, you could ask them to “Choose one of our new products” and link to that section of the webpage.
1.4.1 You must not rely on colour as the only way to convey something to your users. Some of your users can’t see, and some of your users can’t distinguish between colours. For example, if your webpage uses green to highlight the products that your shop has in stock, you could add some text to identify those products, or you could group them under a sub-heading.
1.4.2 If your webpage automatically plays a sound for more than 3 seconds, you must make sure your users can stop the sound or change its volume. Don’t rely on your user turning down the volume on their computer; some users need to hear the screen reader on their computer, and some users just want to keep listening to whatever they were listening before your webpage interrupted them!
1.4.3 You should make sure that your text contrasts enough with its background, so that your users can read it. Bookmark Lea Verou’s Contrast Ratio calculator now. You can enter the text colour and background colour as named colours, or as RGB, RGBa, HSL, or HSLa values. You should make sure that:
normal text that set at 24px or larger has a ratio of at least 3:1;
bold text that set at 18.75px or larger has a ratio of at least 3:1;
all other text has a ratio of at least 4½:1.
You don’t have to do this for disabled form controls, decorative stuff, or logos—but you could!
1.4.4 You should make sure your users can resize the text on your website up to 200% without using their assistive technology—and still access all your content and functionality. You don’t have to do this for subtitles or images of text.
1.4.5 You should avoid using images of text and just use text instead. In 1998, Jeffrey Veen’s first Hot Design Tip said, “Text is text. Graphics are graphics. Don’t confuse them.” Now that you can apply powerful CSS text-styling properties, use CSS Grid to precisely position text, and choose from thousands of web fonts (Jeffrey co-founded Typekit to help with this), you pretty much never need to use images of text. The guidelines say you can use images of text if you let your users specify the font, size, colour, and background of the text in the image of text—but I’ve never seen that on a real website. Also, this doesn’t apply to logos.
1.4.6 Let’s go back to colour contrast for a second. You could make your text contrast even more with its background, so that even more of your users can read it. To do that, use Lea Verou’s Contrast Ratio calculator to make sure that:
normal text that is 24px or larger has a ratio of at least 4½:1;
bold text that 18.75px or larger has a ratio of at least 4½:1;
all other text has a ratio of at least 7:1.
1.4.7 If your website has recorded speech, you could make sure there are no background sounds, or that your users can turn off any background sounds. If that’s not possible, you could make sure that any background sounds that last longer than a couple of seconds are at least four times quieter than the speech. This doesn’t apply to audio Captchas, audio logos, singing, or rapping. (Yes, these guidelines mention rapping!)
1.4.8 You could make sure that your users can reformat blocks of text on your website so they can read them better. To do this, make sure that your users can:
specify the colours of the text and the background, and
make the blocks of text less than 80-characters wide, and
align text to the left (or right for right-to-left languages), and
set the line height to 150%, and
set the vertical distance between paragraphs to 1½ times the line height of the text, and
resize the text (without using their assistive technology) up to 200% and still not have to scroll horizontally to read it.
By the way, when you specify a colour for text, always specify a colour for its background too. Don’t rely on default background colours!
1.4.9 Let’s return to images of text for a second. You could make sure that you use them only for decoration and logos.
Can users operate the controls and links on your website?
The second guideline has criteria that help you prevent your users from asking, “How the **** does this thing work?”
2.1.1 You must make sure that you users can carry out all of your website’s activities with just their keyboard, without time limits for pressing keys. (This doesn’t apply to drawing or anything else that requires a pointing device such as a mouse.) Again, if you use the most appropriate HTML element for each piece of information and for each form element, this should prove easy.
2.1.2 You must make sure that when the user uses the keyboard to focus on some part of your website, they can then move the focus to some other part of your webpage without needing to use a mouse or touch the screen. If your website needs them to do something complex before they can move the focus elsewhere, explain that to your user. These “keyboard traps” have become rare, but beware of forms that move focus from one text box to another as soon as they receive the correct number of characters.
2.1.3 Let’s revisit making sure that you users can carry out all of your website’s activities with just their keyboard, without time limits for pressing keys. You could make sure that your user can do absolutely everything on your website with just the keyboard.
2.2.1 Sometimes people need more time than you might expect to complete a task on your website. If any part of your website imposes a time limit on a task, you must do at least one of these:
let your users turn off the time limit before they encounter it; or
let your users increase the time limit to at least 10 times the default time limit before they encounter it; or
warn your users before the time limit expires and give them at least 20 seconds to extend it, and let them extend it at least 10 times.
Remember: these guidelines are practical. They allow you to enforce time limits for real-time events such as auctions and ticket sales, where increasing or extending time limits wouldn’t make sense. Also, the guidelines allow you to enforce a maximum time limit of 20 hours. The editors chose 20 hours because people need to go to sleep at some stage. See? Practical!
2.2.2 In my experience, this criterion remains the least well-known—even though some users can only use websites that conform to it. If your website presents content alongside other content that can distract users by automatically moving, blinking, scrolling, or updating, you must make sure that your users can:
pause, stop, or hide the other content if it’s not essential and lasts more than 5 seconds; and
pause, stop, hide, or control the frequency of the other content if it automatically updates.
It’s OK if your users miss live information such as stock price updates or football scores; you can’t do anything about that! Also, this doesn’t apply to animations such as progress bars that you put on a website to let all users know that the webpage isn’t frozen.
(If this one sounds complex, just add a pause button to anything that might distract your users.)
2.2.3 Let’s go back to time limits on tasks on your website. You could make your website even easier to use by removing all time limits except those on real-time events such as auctions and ticket sales. That would mean your user wouldn’t need to interact with a timer at all.
2.2.4 You could let your users turn off all interruptions—server updates, promotions, and so on—apart from any emergency information.
2.2.5 This is possibly my favourite of these criteria! After your website logs your user out, you could make sure that when they log in again, they can continue from where they were without having lost any information. Do that, and you’ll be on everyone’s Nice List this Christmas.
2.3.1 You must make sure that nothing flashes more than three times a second on your website, unless you can make sure that the flashes remain below the acceptable general flash and red flash thresholds…
2.3.2 …or you could just make sure that nothing flashes more than three times per second on your website. This is usually an easier goal.
2.4.1 You must make sure that your users can jump past any blocks of content, such as navigation menus, that are repeated throughout your website. You know the drill here: using HTML’s sectioning elements such as header, nav, main, aside, and footer allows users with assistive technology to go straight to the content they need, and adding “Skip Navigation” links allows everyone to get to your main content faster.
2.4.2 You must add a proper title to describe each webpage’s topic. Your webpage won’t even validate without a title element, so make it a useful one.
2.4.3 If your users can focus on links and native form widgets, you must make sure that they can focus on elements in an order that makes sense.
2.4.4 You must make sure that your users can understand the purpose of a link when they read:
the text of the link; or
the text of the paragraph, list item, table cell, or table header for the cell that contains the link; or
the heading above the link.
You don’t have to do that for games and quizzes.
2.4.5 You should give your users multiple ways to find any webpage within a set of webpages. Add site-wide search and a site map and you’re done!
This doesn’t apply for a webpage that is part of a series of actions (like a shopping cart and checkout flow) or to a webpage that is a result of a series of actions (like a webpage confirming that the user has bought what was in the shopping cart).
2.4.6 You should help your users to understand your content by providing:
headings that describe the topics of you content;
labels that describe the purpose of the native form widgets on the webpage.
2.4.7 You should make sure that users can see which element they have focussed on. Next time you use your website, try hitting the Tab key repeatedly. Does it visually highlight each item as it moves focus to it? If it doesn’t, search your CSS to see whether you’ve applied outline: 0; to all elements—that’s usually the culprit. Use the :focus pseudo-element to define how elements should appear when they have focus.
2.4.8 You could help your user to understand where the current webpage is located within your website. Add “breadcrumb navigation” and/or a site map and you’re done.
2.4.9 You could make links even easier to understand, by making sure that your users can understand the purpose of a link when they read the text of the link. Again, you don’t have to do that for games and quizzes.
2.4.10 You could use headings to organise your content by topic.
Can users understand your content?
The third guideline has criteria that help you prevent your users from asking, “What the **** does this mean?”
3.1.1 Let’s start this section with the criterion that possibly takes the least time to implement; you must make sure that the user’s browser can identify the main language that your webpage’s content is written in. For a webpage that has mainly English content, use .
3.1.2 You must specify when content in another language appears in your webpage, like so: I wish you a Joyeux Noël . . You don’t have to do this for proper names, technical terms, or words that you can’t identify a language for. You also don’t have to do it for words from a different language that people consider part of the language around those words; for example, Come to our Christmas rendezvous! is OK.
3.1.3 You could make sure that your users can find out the meaning of any unusual words or phrases, including idioms like “stocking filler” or “Bah! Humbug!” and jargon such as “VoiceOver” and “TalkBack”. Provide a glossary or link to a dictionary.
3.1.4 You could make sure that your users can find out the meaning of any abbreviation. For example, VoiceOver pronounces “Xmas” as “Smas” instead of “Christmas”. Using the abbr element and linking to a glossary can help. (Interestingly, VoiceOver pronounces “abbr” as “abbreviation”!)
3.1.5 Do your users need to be able to read better than a typically educated nine-year-old, to read your content (apart from proper names and titles)? If so, you could provide a version that doesn’t require that level of reading ability, or you could provide images, videos, or audio to explain your content. (You don’t have to add captions or audio description to those videos.)
3.1.6 You could make sure that your users can access the pronunciation of any word in your content if that word’s meaning depends on its pronunciation. For example, the word “close” could have one of two meanings, depending on pronunciation, in a phrase such as, “Ready for Christmas? Close now!”
3.2.1 Some users need to focus on elements to access information about them. You must make sure that focusing on an element doesn’t trigger any major changes, such as opening a new window, focusing on another element, or submitting a form.
3.2.2 Webpages are easier for users when the controls do what they’re supposed to do. Unless you have warned your users about it, you must make sure that changing the value of a control such as a text box, checkbox, or drop-down list doesn’t trigger any major changes, such as opening a new window, focusing on another element, or submitting a form.
3.2.3 To help your users to find the content they want on each webpage, you should put your navigation elements in the same place on each webpage. (This doesn’t apply when your user has changed their preferences or when they use assistive technology to change how your content appears.)
3.2.4 When a set of webpages includes things that have the same functionality on different webpages, you should name those things consistently. For example, don’t use the word “Search” for the search box on one webpage and “Find” for the search box on another webpage within that set of webpages.
3.2.5 Let’s go back to major changes, such as a new window opening, another element taking focus, or a form being submitted. You could make sure that they only happen when users deliberately make them happen, or when you have warned users about them first. For example, you could give the user a button for updating some content instead of automatically updating that content. Also, if a link will open in a new window, you could add the words “opens in new window” to the link text.
3.3.1 Users make mistakes when filling in forms. Your website must identify each mistake to your user, and must describe the mistake to your users in text so that the user can fix it. One way to identify mistakes reliably to your users is to set the aria-invalid attribute to true in the element that has a mistake. That makes sure that users with assistive technology will be alerted about the mistake. Of course, you can then use the [aria-invalid=""true""] attribute selector in your CSS to visually highlight any such mistakes. Also, look into how certain attributes of the input element such as required, type, and list can help prevent and highlight mistakes.
3.3.2 You must include labels or instructions (and possibly examples) in your website’s forms, to help your users to avoid making mistakes.
3.3.3 When your user makes a mistake when filling in a form, your webpage should suggest ways to fix that mistake, if possible. This doesn’t apply in scenarios where those suggestions could affect the security of the content.
3.3.4 Whenever your user submits information that:
has legal or financial consequences; or
affects information that they have previously saved in your website; or
is part of a test
…you should make sure that they can:
undo it; or
correct any mistakes, after your webpage checks their information; or
review, confirm, and correct the information before they finally submit it.
3.3.5 You could help prevent your users from making mistakes by providing obvious, specific help, such as examples, animations, spell-checking, or extra instructions.
3.3.6 Whenever your user submits any information, you could make sure that they can:
undo it; or
correct any mistakes, after your webpage checks their information; or
review, confirm, and correct the information before they finally submit it.
Have you made your website robust enough to work on your users’ browsers and assistive technologies?
The fourth and final guideline has criteria that help you prevent your users from asking, “Why the **** doesn’t this work on my device?”
4.1.1 You must make sure that your website works as well as possible with current and future browsers and assistive technology. Prioritise complying with web standards instead of relying on the capabilities of currently popular devices and browsers. Web developers didn’t expect their users to be unwrapping the Wii U Browser five years ago—who knows what browsers and assistive technologies our users will be unwrapping in five years’ time? Avoid hacks, and use the W3C Markup Validation Service to make sure that your HTML has no errors.
4.1.2 If you develop your own user interface components, you must make their name, role, state, properties, and values available to your user’s browsers and assistive technologies. That should make them almost as accessible as standard HTML elements such as links, buttons, and checkboxes.
“…and a partridge in a pear tree!”
…as that very long Christmas song goes. We’ve covered a lot in this article—because your users have a lot of different levels of ability. Hopefully this has demystified the Web Content Accessibility Guidelines 2.0 for you. Hopefully you spotted a few situations that could arise for users on your website, and you now know how to tackle them.
To start applying what we’ve covered, you might like to look at Sarah Horton and Whitney Quesenbery’s personas for Accessible UX. Discuss the personas, get into their heads, and think about which aspects of your website might cause problems for them. See if you can apply what we’ve covered today, to help users like them to do what they need to do on your website.
How to know when your website is perfectly accessible for everyone
LOL! There will never be a time when your website becomes perfectly accessible for everyone. Don’t aim for that. Instead, aim for regularly testing and making your website more accessible.
Web Content Accessibility Guidelines (WCAG) 2.1
The W3C hope to release the Web Content Accessibility Guidelines (WCAG) 2.1 as a “recommendation” (that’s what the W3C call something that we should start using) by the middle of next year. Ten years may seem like a long time to move from version 2.0 to version 2.1, but consider the scale of the task: the editors have to update the guidelines to cover all the new ways that people interact with new technologies, while keeping the guidelines backwards-compatible. Keep an eye out for 2.1!
You’ll go down in history
One last point: I’ve met a surprising number of web designers and developers who do great work to make their websites more accessible without ever telling their users about it. Some of your potential customers have possibly tried and failed to use your website in the past. They probably won’t try again unless you let them know that things have improved. A quick Twitter search for your website’s name alongside phrases like “assistive technology”, “doesn’t work”, or “#fail” can let you find frustrated users—so you can tell them about how you’re making your website more accessible. Start making your websites work better for everyone—and please, let everyone know.",2017,Alan Dalton,alandalton,2017-12-03T00:00:00+00:00,https://24ways.org/2017/wcag-for-people-who-havent-read-them/,code
267,Taming Complexity,"I’m going to step into my UX trousers for this one. I wouldn’t usually wear them in public, but it’s Christmas, so there’s nothing wrong with looking silly.
Anyway, to business. Wherever I roam, I hear the familiar call for simplicity and the denouncement of complexity. I read often that the simpler something is, the more usable it will be. We understand that simple is hard to achieve, but we push for it nonetheless, convinced it will make what we build easier to use. Simple is better, right?
Well, I’ll try to explore that. Much of what follows will not be revelatory to some but, like all good lessons, I think this serves as a welcome reminder that as we live in a complex world it’s OK to sometimes reflect that complexity in the products we build.
Myths and legends
Less is more, we’ve been told, ever since master of poetic verse Robert Browning used the phrase in 1855. Well, I’ve conducted some research, and it appears he knew nothing of web design. Neither did modernist architect Ludwig Mies van der Rohe, a later pedlar of this worthy yet contradictory notion. Broad is narrow. Tall is short. Eggs are chips. See: anyone can come up with this stuff.
To paraphrase Einstein, simple doesn’t have to be simpler. In other words, simple doesn’t dictate that we remove the complexity. Complex doesn’t have to be confusing; it can be beautiful and elegant. On the web, complex can be necessary and powerful. A website that simplifies the lives of its users by offering them everything they need in one site or screen is powerful. For some, the greater the density of information, the more useful the site.
In our decision-making process, principles such as Occam’s razor’s_razor (in a nutshell: simple is better than complex) are useful, but simple is for the user to determine through their initial impression and subsequent engagement. What appears simple to me or you might appear very complex to someone else, based on their own mental model or needs. We can aim to deliver simple, but they’ll be the judge.
As a designer, developer, content alchemist, user experience discombobulator, or whatever you call yourself, you’re often wrestling with a wealth of material, a huge number of features, and numerous objectives. In many cases, much of that stuff is extraneous, and goes in the dustbin. However, it can be just as likely that there’s a truckload of suggested features and content because it all needs to be there. Don’t be afraid of that weight.
In the right hands, less can indeed mean more, but it’s just as likely that less can very often lead to, well… less.
Complexity is powerful
Simple is the ability to offer a powerful experience without overwhelming the audience or inducing information anxiety. Giving them everything they need, without having them ferret off all over a site to get things done, is important.
It’s useful to ask throughout a site’s lifespan, “does the user have everything they need?” It’s so easy to let our designer egos get in the way and chop stuff out, reduce down to only the things we want to see. That benefits us in the short term, but compromises the audience long-term.
The trick is not to be afraid of complexity in itself, but to avoid creating the perception of complexity. Give a user a flight simulator and they’ll crash the plane or jump out. Give them everything they need and more, but make it feel simple, and you’re building a relationship, empowering people.
This can be achieved carefully with what some call gradual engagement, and often the sensible thing might be to unleash complexity in carefully orchestrated phases, initially setting manageable levels of engagement and interaction, gradually increasing the inherent power of the product and fostering an empowered community.
The design aesthetic
Here’s a familiar scenario: the client or project lead gets overexcited and skips most of the important decision-making, instead barrelling straight into a bout of creative direction Tourette’s. Visually, the design needs to be minimal, white, crisp, full of white space, have big buttons, and quite likely be “clean”. Of course, we all like our websites to be clean as that’s more hygienic.
But what do these words even mean, really? Early in a project they’re abstract distractions, unnecessary constraints. This premature narrowing forces us to think much more about throwing stuff out rather than acknowledging that what we’re building is complex, and many of the components perhaps necessary.
Simple is not a formula. It cannot be achieved just by using a white background, by throwing things away, or by breathing a bellowsful of air in between every element and having it all float around in space. Simple is not a design treatment. Simple is hard. Simple requires deep investigation, a thorough understanding of every aspect of a project, in line with the needs and expectations of the audience.
Recognizing this helps us empathize a little more with those most vocal of UX practitioners. They usually appreciate that our successes depend on a thorough understanding of the user’s mental models and expected outcomes. I personally still consider UX people to be web designers like the rest of us (mainly to wind them up), but they’re web designers that design every decision, and by putting the user experience at the heart of their process, they have a greater chance of finding simplicity in complexity. The visual design aesthetic — the façade — is only a part of that.
Divide and conquer
I’m currently working on an app that’s complex in architecture, and complex in ambition. We’ll be releasing in carefully orchestrated private phases, gradually introducing more complexity in line with the unavoidably complex nature of the objective, but my job is to design the whole, the complete system as it will be when it’s out of beta and beyond.
I’ve noticed that I’m not throwing much out; most of it needs to be there. Therefore, my responsibility is to consider interesting and appropriate methods of navigation and bring everything together logically.
I’m using things like smart defaults, graphical timelines and colour keys to make sense of the complexity, techniques that are sympathetic to the content. They act as familiar points of navigation and reference, yet are malleable enough to change subtly to remain relevant to the information they connect. It’s really OK to have a lot of stuff, so long as we make each component work smartly.
It’s a divide and conquer approach. By finding simplicity and logic in each content bucket, I’ve made more sense of the whole, allowing me to create key layouts where most of the simplified buckets are collated and sometimes combined, providing everything the user needs and expects in the appropriate places.
I’m also making sure I don’t reduce the app’s power. I need to reflect the scale of opportunity, and provide access to or knowledge of the more advanced tools and features for everyone: a window into what they can do and how they can help. I know it’s the minority who will be actively building the content, but the power is in providing those opportunities for all.
Much of this will be familiar to the responsible practitioners who build websites for government, local authorities, utility companies, newspapers, magazines, banking, and we-sell-everything-ever-made online shops. Across the web, there are sites and tools that thrive on complexity.
Alas, the majority of such sites have done little to make navigation intuitive, or empower audiences. Where we can make a difference is by striving to make our UIs feel simple, look wonderful, not intimidating — even if they’re mind-meltingly complex behind that façade.
Embrace, empathize and tame
So, there are loads of ways to exploit complexity, and make it seem simple. I’ve hinted at some methods above, and we’ve already looked at gradual engagement as a way to make sense of complexity, so that’s a big thumbs-up for a release cycle that increases audience power.
Prior to each and every release, it’s also useful to rest on the finished thing for a while and use it yourself, even if you’re itching to release. ‘Ready’ often isn’t, and ‘finished’ never is, and the more time you spend browsing around the sites you build, the more you learn what to question, where to add, or subtract. It’s definitely worth building in some contingency time for sitting on your work, so to speak.
One thing I always do is squint at my layouts. By squinting, I get a sort of abstract idea of the overall composition, and general feel for the thing. It makes my face look stupid, but helps me see how various buckets fit together, and how simple or complex the site feels overall.
I mentioned the need to put our design egos to one side and not throw out anything useful, and I think that’s vital. I’m a big believer in economy, reduction, and removing the extraneous, but I’m usually referring to decoration, bells and whistles, and fluff. I wouldn’t ever advocate the complete removal of powerful content from a project roadmap.
Above all, don’t fear complexity. Embrace and tame it. Work hard to empathize with audience needs, and you can create elegant, playful, risky, surprising, emotive, delightful, and ultimately simple things.",2011,Simon Collison,simoncollison,2011-12-21T00:00:00+00:00,https://24ways.org/2011/taming-complexity/,ux
292,Watch Your Language!,"I’m bilingual. My first language is French. I learned English in my early 20s. Learning a new language later in life meant that I was able to observe my thought processes changing over time. It made me realize that some concepts can’t be expressed in some languages, while other languages express these concepts with ease.
It also helped me understand the way we label languages. English: business. French: romance. Here’s an example of how words, or the absence thereof, can affect the way we think:
In French we love everything. There’s no straightforward way to say we like something, so we just end up loving everything. I love my sisters, I love broccoli, I love programming, I love my partner, I love doing laundry (this is a lie), I love my mom (this is not a lie). I love, I love, I love. It’s no wonder French is considered romantic. When I first learned English I used the word love rather than like because I hadn’t grasped the difference. Needless to say, I’ve scared away plenty of first dates!
Learning another language made me realize the limitations of my native language and revealed concepts I didn’t know existed. Without the nuances a given language provides, we fail to express what we really think. The absence of words in our vocabulary gets in the way of effectively communicating and considering ideas.
When I lived in Montréal, most people in my circle spoke both French and English. I could switch between them when I could more easily express an idea in one language or the other. I liked (or should I say loved?) those conversations. They were meaningful. They were efficient.
I’m quadrilingual. I code in Ruby, HTML/CSS, JavaScript, Python. In the past couple of years I have been lucky enough to write code in these languages at a massive scale. In learning Ruby, much like learning English, I discovered the strengths and limitations of not only the languages I knew but the language I was learning. It taught me to choose the right tool for the job.
When I started working at Shopify, making a change to a view involved copy/pasting HTML and ERB from one view to another. The CSS was roughly structured into modules, but those modules were not responsive to different screen sizes. Our HTML was complete mayhem, and we didn’t consider accessibility. All this made editing views a laborious process.
Grep. Replace all. Test. Ship it. Repeat.
This wasn’t sustainable at Shopify’s scale, so the newly-formed front end team was given two missions:
Make the app responsive (AKA Let’s Make This Thing Responsive ASAP)
Make the view layer scalable and maintainable (AKA Let’s Build a Pattern Library… in Ruby)
Let’s make this thing responsive ASAP
The year was 2015. The Shopify admin wasn’t mobile friendly. Our browser support was set to IE10. We had the wind in our sails. We wanted to achieve complete responsiveness in the shortest amount of time. Our answer: container queries.
It seemed like the obvious decision at the time. We would be able to set rules for each component in isolation and the component would know how to lay itself out on the page regardless of where it was rendered. It would save us a ton of development time since we wouldn’t need to change our markup, it would scale well, and we would achieve complete component autonomy by not having to worry about page layout. By siloing our components, we were going to unlock the ultimate goal of componentization, cutting the tie to external dependencies. We were cool.
Writing the JavaScript handling container queries was my first contribution to Shopify. It was a satisfying project to work on. We could drop our components in anywhere and they would magically look good. It took us less than a couple weeks to push this to production and make our app mostly responsive.
But with time, it became increasingly obvious that this was not as performant as we had hoped. It wasn’t performant at all. Components would jarringly jump around the page before settling in on first paint.
It was only when we started using the flex-wrap: wrap CSS property to build new components that we realized we were not using the right language for the job. So we swapped out JavaScript container queries for CSS flex-wrapping. Even though flex wasn’t yet as powerful as we wanted it to be, it was still a good compromise. Our components stayed independent of the window size but took much less time to render. Best of all: they used CSS instead of relying on JavaScript for layout.
In other words: we were using the wrong language to express our layout to the browser, when another language could do it much more simply and elegantly.
Let’s build a pattern library… in Ruby
In order to make our view layer maintainable, we chose to build a comprehensive library of helpers. This library would generate our markup from a single source of truth, allowing us to make changes system-wide, in one place. No. More. Grepping.
When I joined Shopify it was a Rails shop freshly wounded by a JavaScript framework (See: Batman.js). JavaScript was like Voldemort, the language that could not be named. Because of this baggage, the only way for us to build a pattern library that would get buyin from our developers was to use Rails view helpers. And for many reasons using Ruby was the right choice for us. The time spent ramping developers up on the new UI Components would be negligible since the Ruby API felt familiar. The transition would be simple since we didn’t have to introduce any new technology to the stack. The components would be fast since they would be rendered on the server. We had a plan.
We put in place a set of Rails tools to make it easy to build components, then wrote a bunch of sweet, sweet components using our shiny new tools. To document our design, content and front end patterns we put together an interactive styleguide to demonstrate how every component works. Our research and development department loved it (and still do)! We continue to roll out new components, and generally the project has been successful, though it has had its drawbacks.
Since the Shopify admin is mostly made up of a huge number of forms, most of the content is static. For this reason, using server-rendered components didn’t seem like a problem at the time. With new app features increasing the amount of DOM manipulation needed on the client side, our early design decisions mean making requests to the server for each re-paint. This isn’t going to cut it.
I don’t know the end of this story, because we haven’t written it yet. We’ve been exploring alternatives to our current system to facilitate the rendering of our components on the client, including React, Vue.js, and Web Components, but we haven’t determined the winner yet. Only time (and data gathering) will tell.
Ruby is great but it doesn’t speak the browser’s language efficiently. It was not the right language for the job.
Learning a new spoken language has had an impact on how I write code. It has taught me that you don’t know what you don’t know until you have the language to express it. Understanding the strengths and limitations of any programming language is fundamental to making good design decisions. At the end of the day, you make the best choices with the information you have. But if you still feel like you’re unable to express your thoughts to the fullest with what you know, it might be time to learn a new language.",2016,Annie-Claude Côté,annieclaudecote,2016-12-10T00:00:00+00:00,https://24ways.org/2016/watch-your-language/,code
106,Checking Out: Progress Meters,"It’s the holiday season, so you know what that means: online shopping! When I started developing Web sites back in the 90s, many of my first clients were small local shops wanting to sell their goods online, so I developed many a checkout system. And because of slow dial-up speeds back then, informing the user about where they were in the checkout process was pretty important.
Even though we’re (mostly) beyond the dial-up days, informing users about where they are in a flow is still important. In usability tests at the companies I’ve worked at, I’ve seen time and time again how not adequately informing the user about their state can cause real frustration. This is especially true for two sets of users: mobile users and users of assistive devices, in particular, screen readers.
The progress meter is a very common design solution used to indicate to the user’s state within a flow. On the design side, much effort may go in to crafting a solution that is as visually informative as possible. On the development side, however, solutions range widely. I’ve checked out the checkouts at a number of sites and here’s what I’ve found when it comes to progress meters: they’re sometimes inaccessible and often confusing or unhelpful — all because of the way in which they’re coded. For those who use assistive devices or text-only browsers, there must be a better way to code the progress meter — and there is.
(Note: All code samples are from live sites but have been tweaked to hide the culprits’ identities.)
How not to make progress
A number of sites assemble their progress meters using non- or semi-semantic markup and images with no alternate text. On text-only browsers (like my mobile phone) and to screen readers, this looks and reads like chunks of content with no context given.
Shipping information
Payment information
Place your order
In the above example, the third state, “Place your order”, is the current state. But a screen reader may not know that, and my cell phone only displays ""Shipping informationPayment informationPlace your order"". Not good.
Is this progress?
Other sites present the entire progress meter as a graphic, like the following:
Now, I have no problem with using a graphic to render a very stylish progress meter (my sample above is probably not the most stylish example, of course, but you understand my point). What becomes important in this case is the use of appropriate alternate text to describe the image. Disappointingly, sites today have a wide range of solutions, including using no alternate text. Check out these code samples which call progress meter images.
I think we can all agree that the above is bad, unless you really don’t care whether or not users know where they are in a flow.
The alt text in the example above just copies all of the text found in the graphic, but it doesn’t represent the status at all. So for every page in the checkout, the user sees or hears the same text. Sure, by the second or third page in the flow, the user has figured out what’s going on, but she or he had to think about it. I don’t think that’s good.
The above probably has the best alternate text out of these examples, because the user at least understands that they’re in the Checkout process, on the Place your order page. But going through the flow with alt text like this, the user doesn’t know how many steps are in the flow.
Semantic progress
Of course, there are some sites that use an ordered list when marking up the progress meter. Hooray! Unfortunately, no text-only browser or screen reader would be able to describe the user’s current state given this markup.
shipping information
payment information
place your order
Without CSS enabled, the above is rendered as follows:
Progress at last
We all know that semantic markup makes for the best foundation, so we’ll start with the markup found above. In order to make the state information accessible, let’s add some additional text in paragraph and span elements.
There are three steps in this checkout process.
Enter your shipping information
Enter your payment information
Review details and place your order
Add on some simple CSS to hide the paragraph and spans, and arrange the list items on a single line with a background image to represent the large number, and this is what you’ll get:
There are three steps in this checkout process.
Enter your shipping information
Enter your payment information
Review details and place your order
To display and describe a state as active, add the class “current” to one of the list items. Then change the hidden content such that it better describes the state to the user.
There are three steps in this checkout process.
You are currently entering your shipping information
In the next step, you will enter your payment information
In the last step, you will review the details and place your order
The end result is an attractive progress meter that gives much greater semantic and contextual information.
There are three steps in this checkout process.
You are currently entering your shipping information
In the next step, you will enter your payment information
In the last step, you will review the details and place your order
For example, the above example renders in a text-only browser as follows:
There are three steps in this checkout process.
You are currently entering your shipping information
In the next step, you will enter your payment information
In the last step, you will review the details and place your order
And the screen reader I use for testing announces the following:
There are three steps in this checkout process. List of three items. You are currently entering your shipping information. In the next step, you will enter your payment information. In the last step, you will review the details and place your order. List end.
Here’s a sample code page that summarises this approach.
Happy frustration-free online shopping with this improved progress meter!",2008,Kimberly Blessing,kimberlyblessing,2008-12-12T00:00:00+00:00,https://24ways.org/2008/checking-out-progress-meters/,ux
26,Integrating Contrast Checks in Your Web Workflow,"It’s nearly Christmas, which means you’ll be sure to find an overload of festive red and green decorating everything in sight—often in the ugliest ways possible.
While I’m not here to battle holiday tackiness in today’s 24 ways, it might just be the perfect reminder to step back and consider how we can implement colour schemes in our websites and apps that are not only attractive, but also legible and accessible for folks with various types of visual disabilities.
This simulated photo demonstrates how red and green Christmas baubles could appear to a person affected by protanopia-type colour blindness—not as festive as you might think. Source: Derek Bruff
I’ve been fortunate to work with Simply Accessible to redesign not just their website, but their entire brand. Although the new site won’t be launching until the new year, we’re excited to let you peek under the tree and share a few treats as a case study into how we tackled colour accessibility in our project workflow. Don’t worry—we won’t tell Santa!
Create a colour game plan
A common misconception about accessibility is that meeting compliance requirements hinders creativity and beautiful design—but we beg to differ. Unfortunately, like many company websites and internal projects, Simply Accessible has spent so much time helping others that they had not spent enough time helping themselves to show the world who they really are. This was the perfect opportunity for them to practise what they preached.
After plenty of research and brainstorming, we decided to evolve the existing Simply Accessible brand. Or, rather, salvage what we could. There was no established logo to carry into the new design (it was a stretch to even call it a wordmark), and the Helvetica typography across the site lacked any character. The only recognizable feature left to work with was colour. It was a challenge, for sure: the oranges looked murky and brown, and the blues looked way too corporate for a company like Simply Accessible. We knew we needed to inject a lot of personality.
The old Simply Accessible website and colour palette.
After an audit to round up every colour used throughout the site, we dug in deep and played around with some ideas to bring some new life to this palette.
Choose effective colours
Whether you’re starting from scratch or evolving an existing brand, the first step to having an effective and legible palette begins with your colour choices. While we aren’t going to cover colour message and meaning in this article, it’s important to understand how to choose colours that can be used to create strong contrast—one of the most important ways to create hierarchy, focus, and legibility in your design.
There are a few methods of creating effective contrast.
Light and dark colours
The contrast that exists between light and dark colours is the most important attribute when creating effective contrast.
Try not to use colours that have a similar lightness next to each other in a design.
The red and green colours on the left share a similar lightness and don’t provide enough contrast on their own without making some adjustments. Removing colour and showing the relationship in greyscale reveals that the version on the right is much more effective.
It’s important to remember that red and green colour pairs cause difficulty for the majority of colour-blind people, so they should be avoided wherever possible, especially when placed next to each other.
Complementary contrast
Effective contrast can also be achieved by choosing complementary colours (other than red and green), that are opposite each other on a colour wheel.
These colour pairs generally work better than choosing adjacent hues on the wheel.
Cool and warm contrast
Contrast also exists between cool and warm colours on the colour wheel.
Imagine a colour wheel divided into cool colours like blues, purples, and greens, and compare them to warm colours like reds, oranges and yellows.
Choosing a dark shade of a cool colour, paired with a light tint of a warm colour will provide better contrast than two warm colours or two cool colours.
Develop colour concepts
After much experimentation, we settled on a simple, two-colour palette of blue and orange, a cool-warm contrast colour scheme. We added swatches for call-to-action messaging in green, error messaging in red, and body copy and form fields in black and grey. Shades and tints of blue and orange were added to illustrations and other design elements for extra detail and interest.
First stab at a new palette.
We introduced the new palette for the first time on an internal project to test the waters before going full steam ahead with the website. It gave us plenty of time to get a feel for the new design before sharing it with the public.
Putting the test palette into practice with an internal report
It’s important to be open to changes in your palette as it might need to evolve throughout the design process. Don’t tell your client up front that this palette is set in stone. If you need to tweak the colour of a button later because of legibility issues, the last thing you want is your client pushing back because it’s different from what you promised.
As it happened, we did tweak the colours after the test run, and we even adjusted the logo—what looked great printed on paper looked a little too light on screens.
Consider how colours might be used
Don’t worry if you haven’t had the opportunity to test your palette in advance. As long as you have some well-considered options, you’ll be ready to think about how the colour might be used on the site or app.
Obviously, in such early stages it’s unlikely that you’re going to know every element or feature that will appear on the site at launch time, or even which design elements could be introduced to the site later down the road. There are, of course, plenty of safe places to start.
For Simply Accessible, I quickly mocked up these examples in Illustrator to get a handle on the elements of a website where contrast and legibility matter the most: text colours and background colours. While it’s less important to consider the contrast of decorative elements that don’t convey essential information, it’s important for a reader to be able to discern elements like button shapes and empty form fields.
A basic list of possible colour combinations that I had in mind for the Simply Accessible website
Run initial tests
Once these elements were laid out, I manually plugged in the HTML colour code of each foreground colour and background colour on Lea Verou’s Contrast Checker. I added the results from each colour pair test to my document so we could see at a glance which colours needed adjustment or which colours wouldn’t work at all.
Note: Read more about colour accessibility and contrast requirements
As you can see, a few problems were revealed in this test. To meet the minimum AA compliance, we needed to slightly darken the green, blue, and orange background colours for text—an easy fix. A more complicated problem was apparent with the button colours. I had envisioned some buttons appearing over a blue background, but the contrast ratios were well under 3:1. Although there isn’t a guide in WCAG for contrast requirements of two non-text elements, the ISO and ANSI standard for visible contrast is 3:1, which is what we decided to aim for.
We also checked our colour combinations in Color Oracle, an app that simulates the most extreme forms of colour blindness. It confirmed that coloured buttons over blue backgrounds was simply not going to work. The contrast was much too low, especially for the more common deuteranopia and protanopia-type deficiencies.
How our proposed colour pairs could look to people with three types of colour blindness
Make adjustments if necessary
As a solution, we opted to change all buttons to white when used over dark coloured backgrounds. In addition to increasing contrast, it also gave more consistency to the button design across the site instead of introducing a lot of unnecessary colour variants.
Putting more work into getting compliant contrast ratios at this stage will make the rest of implementation and testing a breeze. When you’ve got those ratios looking good, it’s time to move on to implementation.
Implement colours in style guide and prototype
Once I was happy with my contrast checks, I created a basic style guide and added all the colour values from my colour exploration files, introduced more tints and shades, and added patterned backgrounds. I created examples of every panel style we were planning to use on the site, with sample text, links, and buttons—all with working hover states. Not only does this make it easier for the developer, it allows you to check in the browser for any further contrast issues.
Run a final contrast check
During the final stages of testing and before launch, it’s a good idea to do one more check for colour accessibility to ensure nothing’s been lost in translation from design to code. Unless you’ve introduced massive changes to the design in the prototype, it should be fairly easy to fix any issues that arise, particularly if you’ve stayed on top of updating any revisions in the style guide.
One of the more well-known evaluation tools, WAVE, is web-based and will work in any browser, but I love using Chrome’s Accessibility Tools. Not only are they built right in to the Inspector, but they’ll work if your site is password-protected or private, too.
Chrome’s Accessibility Tools audit feature shows that there are no immediate issues with colour contrast in our prototype
The human touch
Finally, nothing beats a good round of user testing. Even evaluation tools have their flaws. Although they’re great at catching contrast errors for text and backgrounds, they aren’t going to be able to find errors in non-text elements, infographics, or objects placed next to each other where discernible contrast is important.
Our final palette, compared with our initial ideas, was quite different, but we’re proud to say it’s not just compliant, but shows Simply Accessible’s true personality. Who knows, it may not be final at all—there are so many opportunities down the road to explore and expand it further.
Accessibility should never be an afterthought in a project. It’s not as simple as adding alt text to images, or running your site through a compliance checker at the last minute and assuming that a pass means everything is okay. Considering how colour will be used during every stage of your project will help avoid massive problems before launch, or worse, launching with serious issues.
If you find yourself working on a personal project over the Christmas break, try integrating these checks into your workflow and make colour accessibility a part of your New Year’s resolutions.",2014,Geri Coady,gericoady,2014-12-22T00:00:00+00:00,https://24ways.org/2014/integrating-contrast-checks-in-your-web-workflow/,design
246,Designing Your Site Like It’s 1998,"It’s 20 years to the day since my wife and I started Stuff & Nonsense, our little studio and my outlet for creative ideas on the web. To celebrate this anniversary—and my fourteenth contribution to 24 ways— I’d like to explain how I would’ve developed a design for Planes, Trains and Automobiles, one of my favourite Christmas films.
My design for Planes, Trains and Automobiles is fixed at 800px wide.
Developing a framework
I’ll start by using frames to set up the framework for this new website. Frames are individual pages—one for navigation, the other for my content—pulled together to form a frameset. Space is limited on lower-resolution screens, so by using frames I can ensure my navigation always remains visible. I can include any number of frames inside a element.
I add two rows to my ; the first is for my navigation and is 50px tall, the second is for my content and will resize to fill any available space. As I don’t want frame borders or any space between my frames, I set frameborder and framespacing attributes to 0:
[…]
Next I add the source of my two frame documents. I don’t want people to be able to resize or scroll my navigation, so I add the noresize attribute to that frame:
I do want links from my navigation to open in the content frame, so I give each a name so I can specify where I want links to open:
The framework for this website is simple as it contains only two horizontal rows. Should I need a more complex layout, I can nest as many framesets—and as many individual documents—as I need:
Letterbox framesets were common way to deal with multiple screen sizes. In a letterbox, the central frameset had a fixed height and width, while the frames on the top, right, bottom, and left expanded to fill any remaining space.
Handling older browsers
Sadly not every browser supports frames, so I should send a helpful message to people who use older browsers asking them to upgrade. Happily, I can do that using noframes content:
This page uses frames, but your browser doesn’t support them.
Please upgrade your browser.
Forcing someone back into a frame
Sometimes, someone may follow a link to a page from a portal or search engine, or they might attempt to open it in a new window or tab. If that page properly belongs inside a , people could easily miss out on other parts of a design. This short script will prevent this happening and because it’s vanilla Javascript, it doesn’t require a library such as jQuery:
Laying out my page
Before starting my layout, I add a few basic background and colour styles. I must include these attributes in every page on my website:
I want absolute control over how people experience my design and don’t want to allow it to stretch, so I first need a which limits the width of my layout to 800px. The align attribute will keep this in the centre of someone’s screen:
Although they were developed for displaying tabular information, the cells and rows which make up the element make it ideal for the precise implementation of a design. I need several tables—often nested inside each other—to implement my design. These include tables for a banner and three rows of content:
The width of the first table—used for my banner—is fixed to match the logo it contains. As I don’t need borders, padding, or spacing between these cells, I use attributes to remove them:
The next table—which contains the largest image, introduction, and a call-to-action—is one of the most complex parts of my design, so I need to ensure its layout is pixel perfect. To do that I add an extra row at the top of this table and fill each of its cells with tiny transparent images:
The height and width of these “shims” or “spacers” is only 1px but they will stretch to any size without increasing their weight on the page. This makes them perfect for performant website development.
For the hero of this design, I splice up the large image into three separate files and apply each slice as a background to the table cells. I also match the height of those cells to the background images:
[…]
I use tables and spacer images throughout the rest of this design to lay out the various types of content with perfect precision. For example, to add a single-pixel border around my two columns of content, I first apply a blue background to an outer table along with 1px of cellspacing, then simply nest an inner table—this time with a white background—inside it:
Adding details
Tables are fabulous tools for laying out a page, but they’re also useful for implementing details on those pages. I can use a table to add a gradient background, rounded corners, and a shadow to the button which forms my “Buy the DVD” call-to-action. First, I splice my button graphic into three slices; two fixed-width rounded ends, plus a narrow gradient which stretches and makes this button responsive. Then, I add those images as backgrounds and use spacers to perfectly size my button:
I use those same elements to add details to headlines and lists too. Adding a “bullet” to each item in a list needs only two additional table cells, a circular graphic, and a spacer:
Directed by John Hughes
Implementing a typographic hierarchy
So far I’ve explained how to use frames, tables, and spacers to develop a layout for my content, but what about styling that content? I use elements to change the typeface from the browser’s default to any font installed on someone’s device:
Planes, Trains and Automobiles is a comedy film […]
To adjust the size of those fonts, I use the size attribute and a value between the smallest (1) and the largest (7) where 3 is the browser’s default. I use a size of 4 for this headline and 2 for the text which follows:
Steve Martin
An American actor, comedian, writer, producer, and musician.
When I need to change the typeface, perhaps from a sans-serif like Arial to a serif like Times New Roman, I must change the value of the face attribute on every element on all pages on my website.
NB: I use as many elements as needed to create space between headlines and paragraphs.
View the final result (and especially the source.)
My modern day design for Planes, Trains and Automobiles.
I can imagine many people reading this and thinking “This is terrible advice because we don’t develop websites like this in 2018.” That’s true.
We have the ability to embed any number of web fonts into our products and websites and have far more control over type features, leading, ligatures, and sizes:
font-variant-caps: titling-caps;
font-variant-ligatures: common-ligatures;
font-variant-numeric: oldstyle-nums;
Grid has simplified the implementation of even the most complex compound grid down to just a few lines of CSS:
body {
display: grid;
grid-template-columns: 3fr 1fr 2fr 2fr 1fr 3fr;
grid-template-rows: auto;
grid-column-gap: 2vw;
grid-row-gap: 1vh;
}
Flexbox has made it easy to develop flexible components such as navigation links:
nav ul { display: flex; }
nav li { flex: 1; }
Just one line of CSS can create multiple columns of fluid type:
main { column-width: 12em; }
CSS Shapes enable text to flow around irregular shapes including polygons:
[src*=""main-img""] {
float: left;
shape-outside: polygon(…);
}
Today, we wouldn’t dream of using images and a table to add a gradient, rounded corners, and a shadow to a button or link, preferring instead:
.btn {
background: linear-gradient(#8B1212, #DD3A3C);
border-radius: 1em;
box-shadow: 0 2px 4px 0 rgba(0,0,0,0.50), inset 0 -1px 1px 0 rgba(0,0,0,0.50);
}
CSS Custom Properties, feature and media queries, filters, pseudo-elements, and SVG; the list of advances in HTML, CSS, and other technologies goes on. So does our understanding of how best to use them by separating content, structure, presentation, and behaviour. As 2018 draws to a close, we’re certain we know how to design and develop products and websites better than we did at the end of 1998.
Strange as it might seem looking back, in 1998 we were also certain our techniques and technologies were the best for the job. That’s why it’s dangerous to believe with absolute certainty that the frameworks and tools we increasingly rely on today—tools like Bootstrap, Bower, and Brunch, Grunt, Gulp, Node, Require, React, and Sass—will be any more relevant in the future than elements, frames, layout tables, and spacer images are today.
I have no prediction for what the web will be like twenty years from now. However, I want to believe we’ll build on what we’ve learned during these past two decades about the importance of accessibility, flexibility, and usability, and that the mistakes we made while infatuated by technologies won’t be repeated.
Head over to my website if you’d like to read about how I’d implement my design for ‘Planes, Trains and Automobiles’ today.",2018,Andy Clarke,andyclarke,2018-12-23T00:00:00+00:00,https://24ways.org/2018/designing-your-site-like-its-1998/,code
177,"HTML5: Tool of Satan, or Yule of Santa?","It would lead to unseasonal arguments to discuss the title of this piece here, and the arguments are as indigestible as the fourth turkey curry of the season, so we’ll restrict our article to the practical rather than the philosophical: what HTML5 can you reasonably expect to be able to use reliably cross-browser in the early months of 2010?
The answer is that you can use more than you might think, due to the seasonal tinsel of feature-detection and using the sparkly pixie-dust of IE-only VML (but used in a way that won’t damage your Elf).
Canvas
canvas is a 2D drawing API that defines a blank area of the screen of arbitrary size, and allows you to draw on it using JavaScript. The pictures can be animated, such as in this canvas mashup of Wolfenstein 3D and Flickr. (The difference between canvas and SVG is that SVG uses vector graphics, so is infinitely scalable. It also keeps a DOM, whereas canvas is just pixels so you have to do all your own book-keeping yourself in JavaScript if you want to know where aliens are on screen, or do collision detection.)
Previously, you needed to do this using Adobe Flash or Java applets, requiring plugins and potentially compromising keyboard accessibility. Canvas drawing is supported now in Opera, Safari, Chrome and Firefox. The reindeer in the corner is, of course, Internet Explorer, which currently has zero support for canvas (or SVG, come to that).
Now, don’t pull a face like all you’ve found in your Yuletide stocking is a mouldy satsuma and a couple of nuts—that’s not the end of the story. Canvas was originally an Apple proprietary technology, and Internet Explorer had a similar one called Vector Markup Language which was submitted to the W3C for standardisation in 1998 but which, unlike canvas, was not blessed with retrospective standardisation.
What you need, then, is some way for Internet Explorer to translate canvas to VML on-the-fly, while leaving the other, more standards-compliant browsers to use the HTML5. And such a way exists—it’s a JavaScript library called excanvas. It’s downloadable from http://code.google.com/p/explorercanvas/ and it’s simple to include it via a conditional comment in the head for IE:
Simply include this, and your canvas will be natively supported in the modern browsers (and the library won’t even be downloaded) whereas IE will suddenly render your canvas using its own VML engine. Be sure, however, to check it carefully, as the IE JavaScript engine isn’t so fast and you’ll need to be sure that performance isn’t too degraded to use.
Forms
Since the beginning of the Web, developers have been coding forms, and then writing JavaScript to check whether an input is a correctly formed email address, URL, credit card number or conforms to some other pattern. The cumulative labour of the world’s developers over the last 15 years makes whizzing round in a sleigh and delivering presents seem like popping to the corner shop in comparison.
With HTML5, that’s all about to change. As Yaili began to explore on Day 3, a host of new attributes to the input element provide built-in validation for email address formats (input type=email), URLs (input type=url), any pattern that can be expressed with a JavaScript-syntax regex (pattern=""[0-9][A-Z]{3}"") and the like. New attributes such as required, autofocus, input type=number min=3 max=50 remove much of the tedious JavaScript from form validation.
Other, really exciting input types are available (see all input types). The datalist is reminiscent of a select box, but allows the user to enter their own text if they don’t want to choose one of the pre-defined options. input type=range is rendered as a slider, while input type=date pops up a date picker, all natively in the browser with no JavaScript required at all.
Currently, support is most complete in an experimental implementation in Opera and a number of the new attributes in Webkit-based browsers. But don’t let that stop you! The clever thing about the specification of the new Web Forms is that all the new input types are attributes (rather than elements). input defaults to input type=text, so if a browser doesn’t understand a new HTML5 type, it gracefully degrades to a plain text input.
So where does that leave validation in those browsers that don’t support Web Forms? The answer is that you don’t retire your pre-existing JavaScript validation just yet, but you leave it as a fallback after doing some feature detection. To detect whether (say) input type=email is supported, you make a new input type=email with JavaScript but don’t add it to the page. Then, you interrogate your new element to find out what its type attribute is. If it’s reported back as “email”, then the browser supports the new feature, so let it do its work and don’t bring in any JavaScript validation. If it’s reported back as “text”, it’s fallen back to the default, indicating that it’s not supported, so your code should branch to your old validation routines. Alternatively, use the small (7K) Modernizr library which will do this work for you and give you JavaScript booleans like Modernizr.inputtypes[email] set to true or false.
So what does this buy you? Well, first and foremost, you’re future-proofing your code for that time when all browsers support these hugely useful additions to forms. Secondly, you buy a usability and accessibility win. Although it’s tempting to style the stuffing out of your form fields (which can, incidentally, lead to madness), whatever your branding people say, it’s better to leave forms as close to the browser defaults as possible. A browser’s slider and date pickers will be the same across different sites, making it much more comprehensible to users. And, by using native controls rather than faking sliders and date pickers with JavaScript, your forms are much more likely to be accessible to users of assistive technology.
HTML5 DOCTYPE
You can use the new DOCTYPE !doctype html now and – hey presto – you’re writing HTML5, as it’s pretty much a superset of HTML4. There are some useful advantages to doing this. The first is that the HTML5 validator (I use http://html5.validator.nu) also validates ARIA information, whereas the HTML4 validator doesn’t, as ARIA is a new spec developed after HTML4. (Actually, it’s more accurate to say that it doesn’t validate your ARIA attributes, but it doesn’t automatically report them as an error.)
Another advantage is that HTML5 allows tabindex as a global attribute (that is, on any element). Although originally designed as an accessibility bolt-on, I ordinarily advise you don’t use it; a well-structured page should provide a logical tab order through links and form fields already.
However, tabindex=""-1"" is a legal value in HTML5 as it allows for the element to be programmatically focussable by JavaScript. It’s also very useful for correcting a bug in Internet Explorer when used with a keyboard; in-page links go nowhere if the destination doesn’t have a proprietary property called hasLayout set or a tabindex of -1.
So, whether it is the tool of Satan or yule of Santa, HTML5 is just around the corner. Some you can use now, and by the end of 2010 I predict you’ll be able to use a whole lot more as new browser versions are released.",2009,Bruce Lawson,brucelawson,2009-12-05T00:00:00+00:00,https://24ways.org/2009/html5-tool-of-satan-or-yule-of-santa/,code
217,Beyond Web Mechanics – Creating Meaningful Web Design,"It was just over three years ago when I embarked on becoming a web designer, and the first opinion piece about the state of web design I came across was a conference talk by Elliot Jay Stocks called ‘Destroy the Web 2.0 Look’. Elliot’s presentation was a call to arms, a plea to web designers the world over to stop the endless reproductions of the so called ‘Web 2.0 look’.
Three and a half years on from Elliot’s talk, what has changed? Well, from an aesthetic standpoint, not a whole lot. The Web 2.0 look has evolved, but it’s still with us and much of the web remains filled with cookie cutter websites that bear a striking resemblance to one another. This wouldn’t matter so much if these websites were selling comparable services or products, but they’re not. They look similar, they follow the same web design trends; their aesthetic style sends out a very similar message, yet they’re selling completely different services or products. How can you be communicating effectively with your users when your online book store is visually indistinguishable from an online cosmetic store? This just doesn’t make sense.
I don’t want to belittle the current version of the Web 2.0 look for the sake of it. I want to talk about the opportunity we have as web designers to create more meaningful experiences for the people using our websites. Using design wisely gives us the ability to communicate messages, ideas and attitudes that our users will understand and connect with.
Being human
As human beings we respond emotionally to everything around us – people, objects, posters, packaging or websites. We also respond in different ways to different kinds of aesthetic design and style. We care about style and aesthetics deeply, whether we realise it or not. Aesthetic design has the power to attract or repel. We often make decisions based purely on aesthetics and style – and don’t retailers the world over know it! We connect attitudes and strongly held beliefs to style. Individuals will proudly associate themselves with a certain style or aesthetic because it’s an expression of who they are. You know that old phrase, ‘Don’t judge a book by its cover’? Well, the problem is that people do, so it’s important we get the cover right.
Much is made of how to structure web pages, how to create a logical information hierarchy, how to use layout and typography to clearly communicate with your users. It’s important, however, not to mistake clarity of information or legibility with getting your message across. Few users actually read websites word by word: it’s far more likely they’ll just scan the page. If the page is copy-heavy and nothing grabs their attention, they may well just move on. This is why it’s so important to create a visual experience that actually means something to the user.
Meaningful design
When we view a poster or website, we make split-second assessments and judgements of what is in front of us. Our first impressions of what a website does or who it is aimed at are provoked by the style and aesthetic of the website. For example, with clever use of colour, typography, graphic design and imagery we can communicate to users that an organisation is friendly, edgy, compassionate, fun or environmentally conscious.
Using a certain aesthetic we can convey the personality of that organisation, target age ranges, different sexes or cultural groups, communicate brand attributes, and more. We can make our users feel like they’re part of something and, perhaps even more importantly, we can make new users want to be a part of something. And we can achieve all this before the user has read a single word.
By establishing a website’s aesthetic and creating a meaningful visual language, a design is no longer just a random collection of pretty gradients that have been plucked out of thin air. There can be a logic behind the design decisions we make. So, before you slap another generic piece of ribbon or an ultra shiny icon into the top-left corner of your website, think about why you are doing it. If you can’t come up with a reason better than “I saw it on another website”, it’s probably a poor application of style.
Design and style
There are a number of reasons why the web suffers from a lack meaningful design. Firstly, there are too many preconceptions of what a website should look like. It’s too easy for designers to borrow styles from other websites, thereby limiting the range of website designs we see on the web. Secondly, many web designers think of aesthetic design as of secondary importance, which shouldn’t be the case. Designing websites that are accessible and easy to use is, of course, very important but this is the very least a web designer should be delivering. Easy to use websites should come as standard – it’s equally important to create meaningful, compelling and beautiful experiences for everyone who uses our websites. The aesthetics of your site are part of the design, and to ignore this and play down the role of aesthetic design is just a wasted opportunity.
No compromise necessary
Easy to use, accessible websites and beautiful, meaningful aesthetics are not mutually exclusive. The key is to apply style and aesthetic design appropriately. We need to think about who and what we’re designing for and ask ourselves why we’re applying a certain kind of aesthetic style to our design. If you do this, there’s no reason why effective, functional design should come at the expense of jaw-dropping, meaningful aesthetics.
Web designers need to understand the differences between functional design and aesthetic design but, even more importantly, they need to know how to make them work together. It’s combining these elements of design successfully that makes for the best web design in the world.",2010,Mike Kus,mikekus,2010-12-05T00:00:00+00:00,https://24ways.org/2010/beyond-web-mechanics-creating-meaningful-web-design/,design
20,Make Your Browser Dance,"It was a crisp winter’s evening when I pulled up alongside the pier. I stepped out of my car and the bitterly cold sea air hit my face. I walked around to the boot, opened it and heaved out a heavy flight case. I slammed the boot shut, locked the car and started walking towards the venue.
This was it. My first gig. I thought about all those weeks of preparation: editing video clips, creating 3-D objects, making coloured patterns, then importing them all into software and configuring effects to change as the music did; targeting frequency, beat, velocity, modifying size, colour, starting point; creating playlists of these… and working out ways to mix them as the music played.
This was it. This was me VJing.
This was all a lifetime (well a decade!) ago.
When I started web designing, VJing took a back seat. I was more interested in interactive layouts, semantic accessible HTML, learning all the IE bugs and mastering the quirks that CSS has to offer. More recently, I have been excited by background gradients, 3-D transforms, the @keyframe directive, as well as new APIs such as getUserMedia, indexedDB, the Web Audio API
But wait, have I just come full circle? Could it be possible, with these wonderful new things in technologies I am already familiar with, that I could VJ again, right here, in a browser?
Well, there’s only one thing to do: let’s try it!
Let’s take to the dance floor
Over the past couple of years working in The Lab I have learned to take a much more iterative approach to projects than before. One of my new favourite methods of working is to create a proof of concept to make sure my theory is feasible, before going on to create a full-blown product. So let’s take the same approach here.
The main VJing functionality I want to recreate is manipulating visuals in relation to sound. So for my POC I need to create a visual, with parameters that can be changed, then get some sound and see if I can analyse that sound to detect some data, which I can then use to manipulate the visual parameters. Easy, right?
So, let’s start at the beginning: creating a simple visual. For this I’m going to create a CSS animation. It’s just a funky i element with the opacity being changed to make it flash.
See the Pen Creating a light by Rumyra (@Rumyra) on CodePen
A note about prefixes: I’ve left them out of the code examples in this post to make them easier to read. Please be aware that you may need them. I find a great resource to find out if you do is caniuse.com. You can also check out all the code for the examples in this article
Start the music
Well, that’s pretty easy so far. Next up: loading in some sound. For this we’ll use the Web Audio API. The Web Audio API is based around the concept of nodes. You have a source node: the sound you are loading in; a destination node: usually the device’s speakers; and any number of processing nodes in between. All this processing that goes on with the audio is sandboxed within the AudioContext.
So, let’s start by initialising our audio context.
var contextClass = window.AudioContext;
if (contextClass) {
//web audio api available.
var audioContext = new contextClass();
} else {
//web audio api unavailable
//warn user to upgrade/change browser
}
Now let’s load our sound file into the new context we created with an XMLHttpRequest.
function loadSound() {
//set audio file url
var audioFileUrl = '/octave.ogg';
//create new request
var request = new XMLHttpRequest();
request.open(""GET"", audioFileUrl, true);
request.responseType = ""arraybuffer"";
request.onload = function() {
//take from http request and decode into buffer
context.decodeAudioData(request.response, function(buffer) {
audioBuffer = buffer;
});
}
request.send();
}
Phew! Now we’ve loaded in some sound! There are plenty of things we can do with the Web Audio API: increase volume; add filters; spatialisation. If you want to dig deeper, the O’Reilly Web Audio API book by Boris Smus is available to read online free.
All we really want to do for this proof of concept, however, is analyse the sound data. To do this we really need to know what data we have.
Learning the steps
Let’s take a minute to step back and remember our school days and science class. I’m sure if I drew a picture of a sound wave, we would all start nodding our heads.
The sound you hear is caused by pressure differences in the particles in the air. Sound pushes these particles together, causing vibrations. Amplitude is basically strength of pressure. A simple example of change of amplitude is when you increase the volume on your stereo and the output wave increases in size.
This is great when everything is analogue, but the waveform varies continuously and it’s not suitable for digital processing: there’s an infinite set of values. For digital processing, we need discrete numbers.
We have to sample the waveform at set time intervals, and record data such as amplitude and frequency. Luckily for us, just the fact we have a digital sound file means all this hard work is done for us. What we’re doing in the code above is piping that data in the audio context. All we need to do now is access it.
We can do this with the Web Audio API’s analysing functionality. Just pop in an analysing node before we connect the source to its destination node.
function createAnalyser(source) {
//create analyser node
analyser = audioContext.createAnalyser();
//connect to source
source.connect(analyzer);
//pipe to speakers
analyser.connect(audioContext.destination);
}
The data I’m really interested in here is frequency. Later we could look into amplitude or time, but for now I’m going to stick with frequency.
The analyser node gives us frequency data via the getFrequencyByteData method.
Don’t forget to count!
To collect the data from the getFrequencyByteData method, we need to pass in an empty array (a JavaScript typed array is ideal). But how do we know how many items the array will need when we create it?
This is really up to us and how high the resolution of frequencies we want to analyse is. Remember we talked about sampling the waveform; this happens at a certain rate (sample rate) which you can find out via the audio context’s sampleRate attribute. This is good to bear in mind when you’re thinking about your resolution of frequencies.
var sampleRate = audioContext.sampleRate;
Let’s say your file sample rate is 48,000, making the maximum frequency in the file 24,000Hz (thanks to a wonderful theorem from Dr Harry Nyquist, the maximum frequency in the file is always half the sample rate). The analyser array we’re creating will contain frequencies up to this point. This is ideal as the human ear hears the range 0–20,000hz.
So, if we create an array which has 2,400 items, each frequency recorded will be 10Hz apart. However, we are going to create an array which is half the size of the FFT (fast Fourier transform), which in this case is 2,048 which is the default. You can set it via the fftSize property.
//set our FFT size
analyzer.fftSize = 2048;
//create an empty array with 1024 items
var frequencyData = new Uint8Array(1024);
So, with an array of 1,024 items, and a frequency range of 24,000Hz, we know each item is 24,000 ÷ 1,024 = 23.44Hz apart.
The thing is, we also want that array to be updated constantly. We could use the setInterval or setTimeout methods for this; however, I prefer the new and shiny requestAnimationFrame.
function update() {
//constantly getting feedback from data
requestAnimationFrame(update);
analyzer.getByteFrequencyData(frequencyData);
}
Putting it all together
Sweet sticks! Now we have an array of frequencies from the sound we loaded, updating as the sound plays. Now we want that data to trigger our animation from earlier.
We can easily pause and run our CSS animation from JavaScript:
element.style.webkitAnimationPlayState = ""paused"";
element.style.webkitAnimationPlayState = ""running"";
Unfortunately, this may not be ideal as our animation might be a whole heap longer than just a flashing light. We may want to target specific points within that animation to have it stop and start in a visually pleasing way and perhaps not smack bang in the middle.
There is no really easy way to do this at the moment as Zach Saucier explains in this wonderful article. It takes some jiggery pokery with setInterval to try to ascertain how far through the CSS animation you are in percentage terms.
This seems a bit much for our proof of concept, so let’s backtrack a little. We know by the animation we’ve created which CSS properties we want to change. This is pretty easy to do directly with JavaScript.
element.style.opacity = ""1"";
element.style.opacity = ""0.2"";
So let’s start putting it all together. For this example I want to trigger each light as a different frequency plays. For this, I’ll loop through the HTML elements and change the opacity style if the frequency gain goes over a certain threshold.
//get light elements
var lights = document.getElementsByTagName('i');
var totalLights = lights.length;
for (var i=0; i 160){
//start animation on element
lights[i].style.opacity = ""1"";
} else {
lights[i].style.opacity = ""0.2"";
}
}
See all the code in action here. I suggest viewing in a modern browser :)
Awesome! It is true — we can VJ in our browser!
Let’s dance!
So, let’s start to expand this simple example. First, I feel the need to make lots of lights, rather than just a few. Also, maybe we should try a sound file more suited to gigs or clubs.
Check it out!
I don’t know about you, but I’m pretty excited — that’s just a bit of HTML, CSS and JavaScript!
The other thing to think about, of course, is the sound that you would get at a venue. We don’t want to load sound from a file, but rather pick up on what is playing in real time. The easiest way to do this, I’ve found, is to capture what my laptop’s mic is picking up and piping that back into the audio context. We can do this by using getUserMedia.
Let’s include this in this demo. If you make some noise while viewing the demo, the lights will start to flash.
And relax :)
There you have it. Sit back, play some music and enjoy the Winamp like experience in front of you.
So, where do we go from here? I already have a wealth of ideas. We haven’t started with canvas, SVG or the 3-D features of CSS. There are other things we can detect from the audio as well. And yes, OK, it’s questionable whether the browser is the best environment for this. For one, I’m using a whole bunch of nonsensical HTML elements (maybe each animation could be held within a web component in the future). But hey, it’s fun, and it looks cool and sometimes I think it’s OK to just dance.",2013,Ruth John,ruthjohn,2013-12-02T00:00:00+00:00,https://24ways.org/2013/make-your-browser-dance/,code
186,The Web Is Your CMS,"It is amazing what you can do these days with the services offered on the web. Flickr stores terabytes of photos for us and converts them automatically to all kind of sizes, finds people in them and even allows us to edit them online. YouTube does almost the same complete job with videos, LinkedIn allows us to maintain our CV, Delicious our bookmarks and so on.
We don’t have to do these tasks ourselves any more, as all of these systems also come with ways to use the data in the form of Application Programming Interfaces, or APIs for short. APIs give us raw data when we send requests telling the system what we want to get back.
The problem is that every API has a different idea of what is a simple way of accessing this data and in which format to give it back.
Making it easier to access APIs
What we need is a way to abstract the pains of different data formats and authentication formats away from the developer — and this is the purpose of the Yahoo Query Language, or YQL for short.
Libraries like jQuery and YUI make it easy and reliable to use JavaScript in browsers (yes, even IE6) and YQL allows us to access web services and even the data embedded in web documents in a simple fashion – SQL style.
Select * from the web and filter it the way I want
YQL is a web service that takes a few inputs itself:
A query that tells it what to get, update or access
An output format – XML, JSON, JSON-P or JSON-P-X
A callback function (if you defined JSON-P or JSON-P-X)
You can try it out yourself – check out this link to get back Flickr photos for the search term ‘santa’*%20from%20flickr.photos.search%20where%20text%3D%22santa%22&format=xml in XML format. The YQL query for this is
select * from flickr.photos.search where text=""santa""
The easiest way to take your first steps with YQL is to look at the console. There you get sample queries, access to all the data sources available to you and you can easily put together complex queries. In this article, however, let’s use PHP to put together a web page that pulls in Flickr photos, blog posts, Videos from YouTube and latest bookmarks from Delicious.
Check out the demo and get the source code on GitHub.
query->results->results;
/* YouTube output */
$youtube = '';
foreach($results[0]->item as $r){
$cleanHTML = undoYouTubeMarkupCrimes($r->description);
$youtube .= ''.$cleanHTML.' ';
}
$youtube .= ' ';
/* Flickr output */
$flickr = '';
/* Delicious output */
$delicious = '';
/* Blog output */
$blog = '';
function undoYouTubeMarkupCrimes($str){
$cleaner = preg_replace('/555px/','100%',$str);
$cleaner = preg_replace('/width=""[^""]+""/','',$cleaner);
$cleaner = preg_replace('//',' ',$cleaner);
return $cleaner;
}
?>
What we are doing here is create a few different YQL statements and queue them together with the query.multi table. Each of these can be run inside YQL itself. Check out the YouTube, Flickr, Delicious and Blog example in the console if you don’t believe me. The benefit of using this table is that we don’t make individual requests for each query but we get all the data in one single request – which means a much better performing solution as the YQL server farm is faster on the web than our servers.
We point the query to the YQL web service end point and get the resulting data using cURL. All that we need to do then is to convert the returned data to HTML lists that can be printed out inside an HTML template.
Mixing, matching and using HTML as a data source
This was a simple example of what YQL can do for you. Where it gets really powerful however is by mixing and matching different APIs. YQL is also a good tool to get information from HTML documents. By using the html table you can load the content of an HTML document (which gets fixed automatically by HTMLTidy) and use XPATH to filter down results to what you need. Take the following example which takes headlines from the news.bbc.co.uk homepage and runs the results through Yahoo’s Term Extractor API to give you a list of currently hot topics.
select * from search.termextract where context in (
select content from html where url=""http://news.bbc.co.uk"" and xpath=""//table[@width=800]//a""
)
Try it out in the console or see the results here. In English, this means:
Go to http://news.bbc.co.uk and get me the HTML
Run it through HTML Tidy to clean it up.
Get me only the links inside the table with an attribute of width and the value 800
Get only the content of the link and for each of the links
Take the content and send it as context to the Yahoo Term Extractor API
If we choose JSON-P as the output format we can use the outcome directly in JavaScript (see this demo or see its source):
Using JSON, we can also use PHP which means the demo works for everybody – not only those with JavaScript enabled (see this demo or see its source):
query->results->Result);
echo join(' ',$topics);
?>
Summary
This article could only scratch the surface of YQL. You have not only read access to the web but you can also write to web services. For example you can update Twitter, post to your WordPress blog or shorten a URL with bit.ly. Using Open Tables you can add any web service to the YQL interface and you can even run server-side JavaScript which is for example useful to return Flickr photos as HTML or get the HTML content from a document that needs POST data.
The web of data is already here, and using YQL you don’t have to be a web services expert to use it and be part of it.",2009,Christian Heilmann,chrisheilmann,2009-12-17T00:00:00+00:00,https://24ways.org/2009/the-web-is-your-cms/,code
262,Be the Villain,"Inclusive Design is the practice of making products and services accessible to, and usable by as many people as reasonably possible without the need for specialized accommodations. The practice was popularized by author and User Experience Design Director Kat Holmes. If getting you to discover her work is the only thing this article succeeds in doing then I’ll consider it a success.
As a framework for creating resilient solutions to problems, Inclusive Design is incredible. However, the aimless idealistic aspirations many of its newer practitioners default to can oftentimes run into trouble. Without outlining concrete, actionable outcomes that are then vetted by the people you intend to serve, there is the potential to do more harm than good.
When designing, you take a user flow and make sure it can’t be broken. Ensuring that if something is removed, it can be restored. Or that something editable can also be updated at a later date—you know, that kind of thing. What we want to do is avoid surprises. Much like a water slide with a section of pipe missing, a broken flow forcibly ejects a user, to great surprise and frustration. Interactions within a user flow also have to be small enough to be self-contained, so as to avoid creating a none pizza with left beef scenario.
Lately, I’ve been thinking about how to expand on this practice. Watertight user flows make for a great immediate experience, but it’s all too easy to miss the forest for the trees when you’re a product designer focused on cranking out features.
What I’m concerned about is while to trying to envision how a user flow could be broken, you also think about how it could be subverted. In addition to preventing the removal of a section of water slide, you also keep someone from mugging the user when they shoot out the end.
If you pay attention, you’ll start to notice this subversion with increasing frequency:
Domestic abusers using internet-controlled devices to spy on and control their partner.
Zealots tanking a business’ rating on Google because its owners spoke out against unchecked gun violence.
Forcing people to choose between TV or stalking because the messaging center portion of a cable provider’s entertainment package lacks muting or blocking features.
White supremacists tricking celebrities into endorsing anti-Semitic conspiracy theories.
Facebook repeatedly allowing housing, credit, and employment advertisers to discriminate against users by their race, ability, and religion.
White supremacists also using a video game chat service as a recruiting tool.
The unchecked harassment of minors on Instagram.
Swatting.
If I were to guess why we haven’t heard more about this problem, I’d say that optimistically, people have settled out of court. Pessimistically, it’s most likely because we ignore, dismiss, downplay, and suppress those who try to bring it to our attention.
Subverted design isn’t the practice of employing Dark Patterns to achieve your business goals. If you are not familiar with the term, Dark Patterns are the use of cheap user interface tricks and psychological manipulation to get users to act against their own best interests. User Experience consultant Chris Nodder wrote Evil By Design, a fantastic book that unpacks how to detect and think about them, if you’re interested in this kind of thing
Subverted design also isn’t beholden design, or simple lack of attention. This phenomenon isn’t even necessarily premeditated. I think it arises from naïve (or willfully ignorant) design decisions being executed at a historically unprecedented pace and scale. These decisions are then preyed on by the shrewd and opportunistic, used to control and inflict harm on the undeserving. Have system, will game.
This is worth discussing. As the field of design continues to industrialize empathy, it also continues to ignore the very established practice of threat modeling. Most times, framing user experience in terms of how to best funnel people into a service comes with an implicit agreement that the larger system that necessitates the service is worth supporting.
To achieve success in the eyes of their superiors, designers may turn to emotional empathy exercises. By projecting themselves into the perceived surface-level experiences of others, they play-act at understanding how to nudge their targeted demographics into a conversion funnel. This roleplaying exercise has the effect of scoping concerns to the immediate, while simultaneously reinforcing the idea of engagement at all cost within the identified demographic.
The thing is, pure engagement leaves the door wide open for bad actors. Even within the scope of a limited population, the assumption that everyone entering into the funnel is acting with good intentions is a poor one. Security researchers, network administrators, and other professionals who practice threat modeling understand that the opposite is true. By preventing everyone save for well-intentioned users from operating a system within the parameters you set for them, you intentionally limit the scope of abuse that can be enacted.
Don’t get me wrong: being able to escort as many users as you can to the happy path is a foundational skill. But we should also be having uncomfortable conversations about why something unthinkable may in fact not be.
They’re not going to be fun conversations. It’s not going to be easy convincing others that these aren’t paranoid delusions best tucked out of sight in the darkest, dustiest corner of the backlog. Realistically, talking about it may even harm your career.
But consider the alternative. The controlled environment of the hypothetical allows us to explore these issues without propagating harm. Better to be viewed as the office’s resident villain than to have to live with something like this:
If the past few years have taught us anything, it’s that the choices we make—or avoid making—have consequences. Design has been doing a lot of growing up as of late, including waking up to the idea that technology isn’t neutral.
You’re going to have to start thinking the way a monster does—if you can imagine it, chances are someone else can as well. To get into this kind of mindset, inverting the Inclusive Design Principles is a good place to start:
Providing a comparable experience becomes forcing a single path.
Considering situation becomes ignoring circumstance.
Being consistent becomes acting capriciously.
Giving control becomes removing autonomy.
Offering choice becomes limiting options.
Prioritizing content becomes obfuscating purpose.
Adding value becomes filling with gibberish.
Combined, these inverted principles start to paint a picture of something we’re all familiar with: a half-baked, unscrupulous service that will jump at the chance to take advantage of you. This environment is also a perfect breeding ground for spawning bad actors.
These kinds of services limit you in the ways you can interact with them. They kick you out or lock you in if you don’t meet their unnamed criteria. They force you to parse layout, prices, and policies that change without notification or justification. Their controls operate in ways that are unexpected and may shift throughout the experience. Their terms are dictated to you, gaslighting you to extract profit. Heaps of jargon and flashy, unnecessary features are showered on you to distract from larger structural and conceptual flaws.
So, how else can we go about preventing subverted design? Marli Mesibov, Content Strategist and Managing Editor of UX Booth, wrote a brilliant article about how to use Dark Patterns for good—perhaps the most important takeaway being admitting you have a problem in the first place.
Another exercise is asking the question, “What is the evil version of this feature?” Ask it during the ideation phase. Ask it as part of acceptance criteria. Heck, ask it over lunch. I honestly don’t care when, so long as the question is actually raised.
In keeping with the spirit of this article, we can also expand on this line of thinking. Author, scientist, feminist, and pacifist Ursula Franklin urges us to ask, “Whose benefits? Whose risks?” instead of “What benefits? What risks?” in her talk, When the Seven Deadly Sins Became the Seven Cardinal Virtues. Inspired by the talk, Ethan Marcotte discusses how this relates to the web platform in his powerful post, Seven into seven.
Few things in this world are intrinsically altruistic or good—it’s just the nature of the beast. However, that doesn’t mean we have to stand idly by when harm is created. If we can add terms like “anti-pattern” to our professional vocabulary, we can certainly also incorporate phrases like “abuser flow.”
Design finally got a seat at the table. We should use this newfound privilege wisely. Listen to women. Listen to minorities, listen to immigrants, the unhoused, the less economically advantaged, and the less technologically-literate. Listen to the underrepresented and the underprivileged.
Subverted design is a huge problem, likely one that will never completely go away. However, the more of us who put the hard work into being the villain, the more we can lessen the scope of its impact.",2018,Eric Bailey,ericbailey,2018-12-06T00:00:00+00:00,https://24ways.org/2018/be-the-villain/,ux
24,Kill It With Fire! What To Do With Those Dreaded FAQs,"In the mid-1640s, a man named Matthew Hopkins attempted to rid England of the devil’s influence, primarily by demanding payment for the service of tying women to chairs and tossing them into lakes.
Unsurprisingly, his methods garnered criticism. Hopkins defended himself in The Discovery of Witches in 1647, subtitled “Certaine Queries answered, which have been and are likely to be objected against MATTHEW HOPKINS, in his way of finding out Witches.”
Each “querie” was written in the voice of an imagined detractor, and answered in the voice of an imagined defender (always referring to himself as “the discoverer,” or “him”):
Quer. 14.
All that the witch-finder doth is to fleece the country of their money, and therefore rides and goes to townes to have imployment, and promiseth them faire promises, and it may be doth nothing for it, and possesseth many men that they have so many wizzards and so many witches in their towne, and so hartens them on to entertaine him.
Ans.
You doe him a great deale of wrong in every of these particulars.
Hopkins’ self-defense was an early modern English FAQ.
Digital beginnings
Question and answer formatting certainly isn’t new, and stretches back much further than witch-hunt days. But its most modern, most notorious, most reviled incarnation is the internet’s frequently asked questions page.
FAQs began showing up on pre-internet mailing lists as a way for list members to answer and pre-empt newcomers’ repetitive questions:
The presumption was that new users would download archived past messages through ftp. In practice, this rarely happened and the users tended to post questions to the mailing list instead of searching its archives. Repeating the “right” answers becomes tedious…
When all the users of a system can hear all the other users, FAQs make a lot of sense: the conversation needs to be managed and manageable. FAQs were a stopgap for the technological limitations of the time.
But the internet moved past mailing lists. Online information can be stored, searched, filtered, and muted; we choose and control our conversations. New users no longer rely on the established community to answer their questions for them.
And yet, FAQs are still around. They’re a content anti-pattern, replicated from site to site to solve a problem we no longer have.
What we hate when we hate FAQs
As someone who creates and structures online content – always with the goal of making that content as useful as possible to people – FAQs drive me absolutely batty. Almost universally, FAQs represent the opposite of useful. A brief list of their sins:
Double trouble
Duplicated content is practically a given with FAQs. They’re written as though they’ll be accessed in a vacuum – but search results, navigation patterns, and curiosity ensure that users will seek answers throughout the site. Is our goal to split their focus? To make them uncertain of where to look? To divert them to an isolated microcosm of the website? Duplicated content means user confusion (to say nothing of the duplicated workload for maintaining content).
Leaving the job unfinished
Many FAQs fail before they’re even out of the gate, presenting a list of questions that’s incomplete (too short and careless to be helpful) or irrelevant (avoiding users’ real concerns in favor of soundbites). Alternately, if the right questions are there, the answers may be convoluted, jargon-heavy, or otherwise difficult to understand.
Long lists of not-my-question
Getting a single answer often means sifting through a haystack of questions. For each potential question, the user must read, comprehend, assess, move on, rinse, repeat. That’s a lot of legwork for little reward – and a lot of opportunity for mistakes. Users may miss their question, or they may fail to recognize a differently worded version of their question, or they may not notice when their sought-after answer appears somewhere they didn’t expect.
The ventriloquist act
FAQs shift the point of view. While websites speak on behalf of the organization (“our products,” “our services,” “you can call us for assistance,” etc.), FAQs speak as the user – “I can’t find my password” or “How do I sign up?” Both voices are written from the first-person perspective, but speak for different entities, which is disorienting: it breaks the tone and messaging across the website. It’s also presumptuous: why do you get to speak for the user?
These all underscore FAQs’ fatal flaw: they are content without context, delivered without regard for the larger experience of the website. You can hear the absurdity in the name itself: if users are asking the same questions so frequently, then there is an obvious gulf between their needs and the site content. (And if not, then we have a labeling problem.)
Instead of sending users to a jumble of maybe-it’s-here-maybe-it’s-not questions, the answers to FAQs should be found naturally throughout a website. They are not separated, not isolated, not other. They are the content.
To present it otherwise is to create a runaround, and users know it. Jay Martel’s parody, “F.A.Q.s about F.A.Q.s” captures the silliness and frustration of such a system:
Q: Why are you so rude?
A: For that answer, you would have to consult an F.A.Q.s about F.A.Q.s about F.A.Q.s. But your time might be better served by simply abandoning your search for a magic answer and taking responsibility for your own profound ignorance.
FAQs aren’t magic answers. They don’t resolve a content dilemma or even help users. Yet they keep cropping up, defiant, weedy, impossible to eradicate.
Where are they all coming from?
Blame it on this: writing is hard. When generating content, most of us do whatever it takes to get some words on the screen. And the format of question and answer makes it easy: a reactionary first stab at content development.
After all, the point of website content is to answer users’ questions. So this – to give everyone credit – is a really good move. Content creators who think in terms of questions and answers are actually thinking of their users, particularly first-time users, trying to anticipate their needs and write towards them.
It’s a good start. But it’s scaffolding: writing that helps you get to the writing you’re supposed to be doing. It supports you while you write your way to the heart of your content. And once you get there, you have to look back and take the scaffolding down.
Leaving content in the Q&A format that helped you develop it is missing the point. You’re not there to build scaffolding. You have to see your content in its naked purpose and determine the best method for communicating that purpose – and it usually won’t be what got you there.
The goal (to borrow a lesson from content management systems) is to separate the content from its presentation, to let the meaning of the content inform its display.
This is, of course, a nice theory.
An occasionally necessary evil
I have a lot of clients who adore FAQs. They’ve developed their content over a long period of time. They’ve listened to the questions their users are asking. And they’ve answered them all on a page that I simply cannot get them to part with.
Which means I’ve had to consider that there may be occasions where an FAQ page is appropriate.
As an example: one of my clients is a financial office in a large institution. Because this office manages several third-party systems that serve a range of niche audiences, they had developed FAQs that addressed hyper-specific instances of dysfunction within systems for different users – à la “I’m a financial director and my employee submitted an expense report in such-and-such system and it returned such-and-such error. What do I do?”
Yes, this content could be removed from the question format and rewritten. But I’m not sure it would be an improvement. It won’t necessarily resolve concerns about length and searchability, and the different audiences may complicate the delivery. And since the work of rewriting it didn’t fit into the client workflow (small team, no writers, pressed for time), I didn’t recommend the change.
I’ve had to make peace with not being to torch all the FAQs on the internet. Some content, like troubleshooting information or complex procedures, may be better in that format. It may be the smartest way for a particular client to handle that particular information.
Of course, this has to be determined on a case-by-case basis, taking into account the amount of content, the subject matter, the skill levels of the content creators, the publishing workflow, and the search habits of the users.
If you determine that an FAQ page is the only way to go, ask yourself:
Is there a better label or more specific term for the page (support, troubleshooting, product concerns, etc.)?
Is there way to structure the page, categorize the questions, or otherwise make it easier for users to navigate quickly to the answer they need?
Is a question and answer format absolutely the best way to communicate this information?
Form follows function
Just as a question and answer format isn’t necessarily required to deliver the content, neither is it an inappropriate method in and of itself. Content professionals have developed a knee-jerk reaction: It’s an FAQ page! Quick, burn it! Buuuuurn it!
But there’s no inherent evil in questions and answers. Framing content in an interrogatory construct is no more a deal with the devil than subheads and paragraphs, or narrative arcs, or bullet points.
Yes, FAQs are riddled with communication snafus. They deserve, more often than not, to be tied to a chair and thrown into a lake. But that wouldn’t fix our content problems. FAQs are a shiny and obvious target for our frustration, but they’re not unique in their flaws. In any format, in any display, in any kind of page, weak content can rear its ugly, poorly written head.
It’s not the Q&A that’s to blame, it’s bad content. Content without context will always fail users. That’s the real witch in our midst.",2013,Lisa Maria Martin,lisamariamartin,2013-12-08T00:00:00+00:00,https://24ways.org/2013/what-to-do-with-faqs/,content
132,Tasty Text Trimmer,"In most cases, when designing a user interface it’s best to make a decision about how data is best displayed and stick with it. Failing to make a decision ultimately leads to too many user options, which in turn can be taxing on the poor old user.
Under some circumstances, however, it’s good to give the user freedom in customising their workspace. One good example of this is the ‘Article Length’ tool in Apple’s Safari RSS reader. Sliding a slider left of right dynamically changes the length of each article shown. It’s that kind of awesomey magic stuff that’s enough to keep you from sleeping. Let’s build one.
The Setup
Let’s take a page that has lots of long text items, a bit like a news page or like Safari’s RSS items view. If we were to attach a class name to each element we wanted to resize, that would give us something to hook onto from the JavaScript.
Example 1: The basic page.
As you can see, I’ve wrapped my items in a DIV and added a class name of chunk to them. It’s these chunks that we’ll be finding with the JavaScript. Speaking of which …
Our Core Functions
There are two main tasks that need performing in our script. The first is to find the chunks we’re going to be resizing and store their original contents away somewhere safe. We’ll need this so that if we trim the text down we’ll know what it was if the user decides they want it back again. We’ll call this loadChunks.
var loadChunks = function(){
var everything = document.getElementsByTagName('*');
var i, l;
chunks = [];
for (i=0, l=everything.length; i -1){
chunks.push({
ref: everything[i],
original: everything[i].innerHTML
});
}
}
};
The variable chunks is stored outside of this function so that we can access it from our next core function, which is doTrim.
var doTrim = function(interval) {
if (!chunks) loadChunks();
var i, l;
for (i=0, l=chunks.length; i';
s +=' ';
document.getElementById('slider').innerHTML = s;
}
The other important factor to consider is that a slider can be tricky to use unless you have good eyesight and pretty well controlled motor skills. Therefore we should provide a method of changing the value by the keyboard.
I’ve done this by making the icons at either end of the slider links so they can be tabbed to. Clicking on either icon fires the appropriate JavaScript function to show more or less of the text.
In Conclusion
The upshot of all this is that without JavaScript the page just shows all the text as it normally would. With JavaScript we have a slider for trimming the text excepts that can be controlled with the mouse or with a keyboard.
If you’re like me and have just scrolled to the bottom to find the working demo, here it is again:
Try the Tasty Text Trimmer
Trimmer for Christmas? Don’t say I never give you anything!",2006,Drew McLellan,drewmclellan,2006-12-01T00:00:00+00:00,https://24ways.org/2006/tasty-text-trimmer/,code
260,The Art of Mathematics: A Mandala Maker Tutorial,"In front-end development, there’s often a great deal of focus on tools that aim to make our work more efficient. But what if you’re new to web development? When you’re just starting out, the amount of new material can be overwhelming, particularly if you don’t have a solid background in Computer Science. But the truth is, once you’ve learned a little bit of JavaScript, you can already make some pretty impressive things.
A couple of years back, when I was learning to code, I started working on a side project. I wanted to make something colorful and fun to share with my friends. This is what my app looks like these days:
Mandala Maker user interface
The coolest part about it is the fact that it’s a tool: anyone can use it to create something original and brand new.
In this tutorial, we’ll build a smaller version of this app – a symmetrical drawing tool in ES5, JavaScript and HTML5. The tutorial app will have eight reflections, a color picker and a Clear button. Once we’re done, you’re on your own and can tweak it as you please. Be creative!
Preparations: a blank canvas
The first thing you’ll need for this project is a designated drawing space. We’ll use the HTML5 canvas element and give it a width and a height of 600px (you can set the dimensions to anything else if you like).
Files
Create 3 files: index.html, styles.css, main.js. Don’t forget to include your JS and CSS files in your HTML.
Your browser doesn't support canvas.
I’ll ask you to update your HTML file at a later point, but the CSS file we’ll start with will stay the same throughout the project. This is the full CSS we are going to use:
body {
background-color: #ccc;
text-align: center;
}
canvas {
touch-action: none;
background-color: #fff;
}
button {
font-size: 110%;
}
Next steps
We are done with our preparations and ready to move on to the actual tutorial, which is made up of 4 parts:
Building a simple drawing app with one line and one color
Adding a Clear button and a color picker
Adding more functionality: 2 line drawing (add the first reflection)
Adding more functionality: 8 line drawing (add 6 more reflections!)
Interactive demos
This tutorial will be accompanied by four CodePens, one at the end of each section. In my own app I originally used mouse events, and only added touch events when I realized mobile device support was (A) possible, and (B) going to make my app way more accessible. For the sake of code simplicity, I decided that in this tutorial app I will only use one event type, so I picked a third option: pointer events. These are supported by some desktop browsers and some mobile browsers. An up-to-date version of Chrome is probably your best bet.
Part 1: A simple drawing app
Let’s get started with our main.js file. Our basic drawing app will be made up of 6 functions: init, drawLine, stopDrawing, recordPointerLocation, handlePointerMove, handlePointerDown. It also has nine variables:
var canvas, context, w, h,
prevX = 0, currX = 0, prevY = 0, currY = 0,
draw = false;
The variables canvas and context let us manipulate the canvas. w is the canvas width and h is the canvas height. The four coordinates are used for tracking the current and previous location of the pointer. A short line is drawn between (prevX, prevY) and (currX, currY) repeatedly many times while we move the pointer upon the canvas. For your drawing to appear, three conditions must be met: the pointer (be it a finger, a trackpad or a mouse) must be down, it must be moving and the movement has to be on the canvas. If these three conditions are met, the boolean draw is set to true.
1. init
Responsible for canvas set up, this listens to pointer events and the location of their coordinates and sets everything in motion by calling other functions, which in turn handle touch and movement events.
function init() {
canvas = document.querySelector(""canvas"");
context = canvas.getContext(""2d"");
w = canvas.width;
h = canvas.height;
canvas.onpointermove = handlePointerMove;
canvas.onpointerdown = handlePointerDown;
canvas.onpointerup = stopDrawing;
canvas.onpointerout = stopDrawing;
}
2. drawLine
This is called to action by handlePointerMove() and draws the pointer path. It only runs if draw = true. It uses canvas methods you can read about in the canvas API documentation. You can also learn to use the canvas element in this tutorial.
lineWidth and linecap set the properties of our paint brush, or digital pen, but pay attention to beginPath and closePath. Between those two is where the magic happens: moveTo and lineTo take canvas coordinates as arguments and draw from (a,b) to (c,d), which is to say from (prevX,prevY) to (currX,currY).
function drawLine() {
var a = prevX,
b = prevY,
c = currX,
d = currY;
context.lineWidth = 4;
context.lineCap = ""round"";
context.beginPath();
context.moveTo(a, b);
context.lineTo(c, d);
context.stroke();
context.closePath();
}
3. stopDrawing
This is used by init when the pointer is not down (onpointerup) or is out of bounds (onpointerout).
function stopDrawing() {
draw = false;
}
4. recordPointerLocation
This tracks the pointer’s location and stores its coordinates. Also, you need to know that in computer graphics the origin of the coordinate space (0,0) is at the top left corner, and all elements are positioned relative to it. When we use canvas we are dealing with two coordinate spaces: the browser window and the canvas itself. This function converts between the two: it subtracts the canvas offsetLeft and offsetTop so we can later treat the canvas as the only coordinate space. If you are confused, read more about it.
function recordPointerLocation(e) {
prevX = currX;
prevY = currY;
currX = e.clientX - canvas.offsetLeft;
currY = e.clientY - canvas.offsetTop;
}
5. handlePointerMove
This is set by init to run when the pointer moves. It checks if draw = true. If so, it calls recordPointerLocation to get the path and drawLine to draw it.
function handlePointerMove(e) {
if (draw) {
recordPointerLocation(e);
drawLine();
}
}
6. handlePointerDown
This is set by init to run when the pointer is down (finger is on touchscreen or mouse it clicked). If it is, calls recordPointerLocation to get the path and sets draw to true. That’s because we only want movement events from handlePointerMove to cause drawing if the pointer is down.
function handlePointerDown(e) {
recordPointerLocation(e);
draw = true;
}
Finally, we have a working drawing app. But that’s just the beginning!
See the Pen Mandala Maker Tutorial: Part 1 by Hagar Shilo (@hagarsh) on CodePen.
Part 2: Add a Clear button and a color picker
Now we’ll update our HTML file, adding a menu div with an input of the type and class color and a button of the class clear.
Your browser doesn't support canvas.
Clear
Color picker
This is our new color picker function. It targets the input element by its class and gets its value.
function getColor() {
return document.querySelector("".color"").value;
}
Up until now, the app used a default color (black) for the paint brush/digital pen. If we want to change the color we need to use the canvas property strokeStyle. We’ll update drawLine by adding strokeStyle to it and setting it to the input value by calling getColor.
function drawLine() {
//...code...
context.strokeStyle = getColor();
context.lineWidth = 4;
context.lineCap = ""round"";
//...code...
}
Clear button
This is our new Clear function. It responds to a button click and displays a dialog asking the user if she really wants to delete the drawing.
function clearCanvas() {
if (confirm(""Want to clear?"")) {
context.clearRect(0, 0, w, h);
}
}
The method clearRect takes four arguments. The first two (0,0) mark the origin, which is actually the top left corner of the canvas. The other two (w,h) mark the full width and height of the canvas. This means the entire canvas will be erased, from the top left corner to the bottom right corner.
If we were to give clearRect a slightly different set of arguments, say (0,0,w/2,h), the result would be different. In this case, only the left side of the canvas would clear up.
Let’s add this event handler to init:
function init() {
//...code...
canvas.onpointermove = handleMouseMove;
canvas.onpointerdown = handleMouseDown;
canvas.onpointerup = stopDrawing;
canvas.onpointerout = stopDrawing;
document.querySelector("".clear"").onclick = clearCanvas;
}
See the Pen Mandala Maker Tutorial: Part 2 by Hagar Shilo (@hagarsh) on CodePen.
Part 3: Draw with 2 lines
It’s time to make a line appear where no pointer has gone before. A ghost line!
For that we are going to need four new coordinates: a', b', c' and d' (marked in the code as a_, b_, c_ and d_). In order for us to be able to add the first reflection, first we must decide if it’s going to go over the y-axis or the x-axis. Since this is an arbitrary decision, it doesn’t matter which one we choose. Let’s go with the x-axis.
Here is a sketch to help you grasp the mathematics of reflecting a point across the x-axis. The coordinate space in my sketch is different from my explanation earlier about the way the coordinate space works in computer graphics (more about that in a bit!).
Now, look at A. It shows a point drawn where the pointer hits, and B shows the additional point we want to appear: a reflection of the point across the x-axis. This is our goal.
A sketch illustrating the mathematics of reflecting a point.
What happens to the x coordinates?
The variables a/a' and c/c' correspond to prevX and currX respectively, so we can call them “the x coordinates”. We are reflecting across x, so their values remain the same, and therefore a' = a and c' = c.
What happens to the y coordinates?
What about b' and d'? Those are the ones that have to change, but in what way? Thanks to the slightly misleading sketch I showed you just now (of A and B), you probably think that the y coordinates b' and d' should get the negative values of b and d respectively, but nope. This is computer graphics, remember? The origin is at the top left corner and not at the canvas center, and therefore we get the following values: b = h - b, d' = h - d, where h is the canvas height.
This is the new code for the app’s variables and the two lines: the one that fills the pointer’s path and the one mirroring it across the x-axis.
function drawLine() {
var a = prevX, a_ = a,
b = prevY, b_ = h-b,
c = currX, c_ = c,
d = currY, d_ = h-d;
//... code ...
// Draw line #1, at the pointer's location
context.moveTo(a, b);
context.lineTo(c, d);
// Draw line #2, mirroring the line #1
context.moveTo(a_, b_);
context.lineTo(c_, d_);
//... code ...
}
In case this was too abstract for you, let’s look at some actual numbers to see how this works.
Let’s say we have a tiny canvas of w = h = 10. Now let a = 3, b = 2, c = 4 and d = 3.
So b' = 10 - 2 = 8 and d' = 10 - 3 = 7.
We use the top and the left as references. For the y coordinates this means we count from the top, and 8 from the top is also 2 from the bottom. Similarly, 7 from the top is 3 from the bottom of the canvas. That’s it, really. This is how the single point, and a line (not necessarily a straight one, by the way) is made up of many, many small segments that are similar to point in behavior.
If you are still confused, I don’t blame you.
Here is the result. Draw something and see what happens.
See the Pen Mandala Maker Tutorial: Part 3 by Hagar Shilo (@hagarsh) on CodePen.
Part 4: Draw with 8 lines
I have made yet another confusing sketch, with points C and D, so you understand what we’re trying to do. Later on we’ll look at points E, F, G and H as well. The circled point is the one we’re adding at each particular step. The circled point at C has the coordinates (-3,2) and the circled point at D has the coordinates (-3,-2). Once again, keep in mind that the origin in the sketches is not the same as the origin of the canvas.
A sketch illustrating points C and D.
This is the part where the math gets a bit mathier, as our drawLine function evolves further. We’ll keep using the four new coordinates: a', b', c' and d', and reassign their values for each new location/line. Let’s add two more lines in two new locations on the canvas. Their locations relative to the first two lines are exactly what you see in the sketch above, though the calculation required is different (because of the origin points being different).
function drawLine() {
//... code ...
// Reassign values
a_ = w-a; b_ = b;
c_ = w-c; d_ = d;
// Draw the 3rd line
context.moveTo(a_, b_);
context.lineTo(c_, d_);
// Reassign values
a_ = w-a; b_ = h-b;
c_ = w-c; d_ = h-d;
// Draw the 4th line
context.moveTo(a_, b_);
context.lineTo(c_, d_);
//... code ...
What is happening?
You might be wondering why we use w and h as separate variables, even though we know they have the same value. Why complicate the code this way for no apparent reason? That’s because we want the symmetry to hold for a rectangular canvas as well, and this way it will.
Also, you may have noticed that the values of a' and c' are not reassigned when the fourth line is created. Why write their value assignments twice? It’s for readability, documentation and communication. Maintaining the quadruple structure in the code is meant to help you remember that all the while we are dealing with two y coordinates (current and previous) and two x coordinates (current and previous).
What happens to the x coordinates?
As you recall, our x coordinates are a (prevX) and c (currX).
For the third line we are adding, a' = w - a and c' = w - c, which means…
For the fourth line, the same thing happens to our x coordinates a and c.
What happens to the y coordinates?
As you recall, our y coordinates are b (prevY) and d (currY).
For the third line we are adding, b' = b and d' = d, which means the y coordinates are the ones not changing this time, making this is a reflection across the y-axis.
For the fourth line, b' = h - b and d' = h - d, which we’ve seen before: that’s a reflection across the x-axis.
We have four more lines, or locations, to define. Note: the part of the code that’s responsible for drawing a micro-line between the newly calculated coordinates is always the same:
context.moveTo(a_, b_);
context.lineTo(c_, d_);
We can leave it out of the next code snippets and just focus on the calculations, i.e, the reassignments.
Once again, we need some concrete examples to see where we’re going, so here’s another sketch! The circled point E has the coordinates (2,3) and the circled point F has the coordinates (2,-3). The ability to draw at A but also make the drawing appear at E and F (in addition to B, C and D that we already dealt with) is the functionality we are about to add to out code.
A sketch illustrating points E and F.
This is the code for E and F:
// Reassign for 5
a_ = w/2+h/2-b; b_ = w/2+h/2-a;
c_ = w/2+h/2-d; d_ = w/2+h/2-c;
// Reassign for 6
a_ = w/2+h/2-b; b_ = h/2-w/2+a;
c_ = w/2+h/2-d; d_ = h/2-w/2+c;
Their x coordinates are identical and their y coordinates are reversed to one another.
This one will be out final sketch. The circled point G has the coordinates (-2,3) and the circled point H has the coordinates (-2,-3).
A sketch illustrating points G and H.
This is the code:
// Reassign for 7
a_ = w/2-h/2+b; b_ = w/2+h/2-a;
c_ = w/2-h/2+d; d_ = w/2+h/2-c;
// Reassign for 8
a_ = w/2-h/2+b; b_ = h/2-w/2+a;
c_ = w/2-h/2+d; d_ = h/2-w/2+c;
//...code...
}
Once again, the x coordinates of these two points are the same, while the y coordinates are different. And once again I won’t go into the full details, since this has been a long enough journey as it is, and I think we’ve covered all the important principles. But feel free to play around with the code and change it. I really recommend commenting out the code for some of the points to see what your drawing looks like without them.
I hope you had fun learning! This is our final app:
See the Pen Mandala Maker Tutorial: Part 4 by Hagar Shilo (@hagarsh) on CodePen.",2018,Hagar Shilo,hagarshilo,2018-12-02T00:00:00+00:00,https://24ways.org/2018/the-art-of-mathematics/,code
209,Feeding the Audio Graph,"In 2004, I was given an iPod.
I count this as one of the most intuitive pieces of technology I’ve ever owned. It wasn’t because of the the snazzy (colour!) menus or circular touchpad. I loved how smoothly it fitted into my life. I could plug in my headphones and listen to music while I was walking around town. Then when I got home, I could plug it into an amplifier and carry on listening there.
There was no faff. It didn’t matter if I could find my favourite mix tape, or if my WiFi was flakey - it was all just there.
Nowadays, when I’m trying to pair my phone with some Bluetooth speakers, or can’t find my USB-to-headphone jack, or even access any music because I don’t have cellular reception; I really miss this simplicity.
The Web Audio API
I think the Web Audio API feels kind of like my iPod did.
It’s different from most browser APIs - rather than throwing around data, or updating DOM elements - you plug together a graph of audio nodes, which the browser uses to generate, process, and play sounds.
The thing I like about it is that you can totally plug it into whatever you want, and it’ll mostly just work.
So, let’s get started. First of all we want an audio source.
(Song - Night Owl by Broke For Free)
This totally works. However, it’s not using the Web Audio API, so we can’t access or modify the sound it makes.
To hook this up to our audio graph, we can use an AudioSourceNode. This captures the sound from the element, and lets us connect to other nodes in a graph.
const audioCtx = new AudioContext()
const audio = document.querySelector('audio')
const input = audioCtx.createAudioSourceNode(audio)
input.connect(audioCtx.destination)
Great. We’ve made something that looks and sounds exactly the same as it did before. Go us.
Gain
Let’s plug in a GainNode - this allows you to alter the amplitude (volume) of an an audio stream.
We can hook this node up to an element by setting the gain property of the node. (The syntax for this is kind of weird because it’s an AudioParam which has options to set values at precise intervals).
const node = audioCtx.createGain()
const input = document.querySelector('input')
input.oninput = () => node.gain.value = parseFloat(input.value)
input.connect(node)
node.connect(audioCtx.destination)
You can now see a range input, which can be dragged to update the state of our graph. This input could be any kind of element, so now you’ll be free to build the volume control of your dreams.
There’s a number of nodes that let you modify/filter an audio stream in more interesting ways. Head over to the MDN Web Audio page for a list of them.
Analysers
Something else we can add to our graph is an AnalyserNode. This doesn’t modify the audio at all, but allows us to inspect the sounds that are flowing through it. We can put this into our graph between our AudioSourceNode and the GainNode.
const analyser = audioCtx.createAnalyser()
input.connect(analyser)
analyser.connect(gain)
gain.connect(audioCtx.destination)
And now we have an analyser. We can access it from elsewhere to drive any kind of visuals. For instance, if we wanted to draw lines on a canvas we could totally do that:
const waveform = new Uint8Array(analyser.fftSize)
const frequencies = new Uint8Array(analyser.frequencyBinCount)
const ctx = canvas.getContext('2d')
const loop = () => {
requestAnimationFrame(loop)
analyser.getByteTimeDomainData(waveform)
analyser.getByteFrequencyData(frequencies)
ctx.beginPath()
waveform.forEach((f, i) => ctx.lineTo(i, f))
ctx.lineTo(0,255)
frequencies.forEach((f, i) => ctx.lineTo(i, 255-f))
ctx.stroke()
}
loop()
You can see that we have two arrays of data available (I added colours for clarity):
The waveform - the raw samples of the audio being played.
The frequencies - a fourier transform of the audio passing through the node.
What’s cool about this is that you’re not tied to any specific functionality of the Web Audio API. If it’s possible for you to update something with an array of numbers, then you can just apply it to the output of the analyser node.
For instance, if we wanted to, we could definitely animate a list of emoji in time with our music.
spans.forEach(
(s, i) => s.style.transform = `scale(${1 + (frequencies[i]/100)})`
)
🔈🎤🎤🎤🎺🎷📯🎶🔊🎸🎺🎤🎸🎼🎷🎺🎻🎸🎻🎺🎸🎶🥁🎶🎵🎵🎷📯🎸🎹🎤🎷🎻🎷🔈🔊📯🎼🎤🎵🎼📯🥁🎻🎻🎤🔉🎵🎹🎸🎷🔉🔈🔉🎷🎶🔈🎸🎸🎻🎤🥁🎼📯🎸🎸🎼🎸🥁🎼🎶🎶🥁🎤🔊🎷🔊🔈🎺🔊🎻🎵🎻🎸🎵🎺🎤🎷🎸🎶🎼📯🔈🎺🎤🎵🎸🎸🔊🎶🎤🥁🎵🎹🎸🔈🎻🔉🥁🔉🎺🔊🎹🥁🎷📯🎷🎷🎤🎸🔉🎹🎷🎸🎺🎼🎤🎼🎶🎷🎤🎷📯📯🎻🎤🎷📯🎹🔈🎵🎹🎼🔊🔉🔉🔈🎶🎸🥁🎺🔈🎷🎵🔉🥁🎷🎹🎷🔊🎤🎤🔊🎤🎤🎹🎸🎹🔉🎷
Generating Audio
So far, we’ve been using the element as a source of sound.
There’s a few other sources of audio that we can use. We’ll look at the AudioBufferNode - which allows you to manually generate a sound sample, and then connect it to our graph.
First we have to create an AudioBuffer, which holds our raw data, then we pass that to an AudioBufferNode which we can then treat just like our AudioSource node. This can get a bit boring, so we’ll use a helper method that makes it simpler to generate sounds.
const generator = (audioCtx, target) => (seconds, fn) => {
const { sampleRate } = audioCtx
const buffer = audioCtx.createBuffer(
1, sampleRate * seconds, sampleRate
)
const data = buffer.getChannelData(0)
for (var i = 0; i < data.length; i++) {
data[i] = fn(i / sampleRate, seconds)
}
return () => {
const source = audioCtx.createBufferSource()
source.buffer = audioBuffer
source.connect(target || audioCtx.destination)
source.start()
}
}
const sound = generator(audioCtx, gain)
Our wrapper will let us provide a function that maps time (in seconds) to a sample (between 1 and -1). This generates a waveform, like we saw before with the analyser node.
For example, the following will generate 0.75 seconds of white noise at 20% volume.
const noise = sound(0.75, t => Math.random() * 0.2)
button.onclick = noise
Noise
Now we’ve got a noisy button! Handy.
Rather than having a static set of audio nodes, each time we click the button, we add a new node to our graph. Although this feels inefficient, it’s not actually too bad - the browser can do a good job of cleaning up old nodes once they’ve played.
An interesting property of defining sounds as functions is that we can combine multiple function to generate new sounds. So if we wanted to fade our noise in and out, we could write a higher order function that does that.
const ease = fn => (t, s) =>
fn(t) * Math.sin((t / s) * Math.PI)
const noise = sound(0.75, ease(t => Math.random() * 0.2))
ease(noise)
And we can do more than just white noise - if we use Math.sin, we can generate some nice pure tones.
// Math.sin with period of 0..1
const wave = v => Math.sin(Math.PI * 2 * v)
const hz = f => t => wave(t * f)
const _440hz = sound(0.75, ease(hz(440)))
const _880hz = sound(0.75, ease(hz(880)))
440Hz
880Hz
We can also make our functions more complex. Below we’re combining several frequencies to make a richer sounding tone.
const harmony = f => [4, 3, 2, 1].reduce(
(v, h, i) => (sin(f * h) * (i+1) ) + v
)
const a440 = sound(0.75, ease(harmony(440)))
440Hz
880Hz
Cool.
We’re still not using any audio-specific functionality, so we can repurpose anything that does an operation on data. For example, we can use d3.js - usually used for interactive data visualisations - to generate a triangular waveform.
const triangle = d3.scaleLinear()
.domain([0, .5, 1])
.range([-1, 1, -1])
const wave = t => triangle(t % 1)
const a440 = sound(0.75, ease(harmony(440)))
440Hz
880Hz
It’s pretty interesting to play around with different functions. I’ve plonked everything in jsbin if you want to have a play yourself.
A departure from best practice
We’ve been generating our audio from scratch, but most of what we’ve looked at can be implemented by a series of native Web Audio nodes. This would be way performant (because it’s not happening on the main thread), and more flexible in some ways (because you can set timings dynamically whilst the note is playing). But we’re going to stay with this approach because it’s fun, and sometimes the fun thing to do might not technically be the best thing to do.
Making a keyboard
Having a button that makes a sound is totally great, but how about lots of buttons that make lots of sounds? Yup, totally greater-er.
The first thing we need to know is the frequency of each note. I thought this would be awkward because pianos were invented more than 250 years before the Hz unit was defined, so surely there wouldn’t be a simple mapping between the two?
const freq = note => 27.5 * Math.pow(2, (note - 21) / 12)
This equation blows my mind; I’d never really figured how tightly music and maths fit together. When you see a chord or melody, you can directly map it back to a mathematical pattern.
Our keyboard is actually an SVG picture of a keyboard, so we can traverse the elements of it and map each element to a sound generated by one of the functions that we came up with before.
Array.from(svg.querySelector('rect'))
.sort((a, b) => + a.x - b.x)
.forEach((key, i) =>
key.addEventListener('touchstart',
sound(0.75, ease(harmony(freq(i + 48))))
)
)
rect {stroke: #ddd;}
rect:hover {opacity: 0.8; stroke: #000}
Et voilà. We have a keyboard.
What I like about this is that it’s completely pure - there’s no lookup tables or hardcoded attributes; we’ve just defined a mapping from SVG elements to the sound they should probably make.
Doing better in the future
As I mentioned before, this could be implemented more performantly with Web Audio nodes, or even better - use something like Tone.js to be performant for you.
Web Audio has been around for a while, though we’re getting new challenges with immersive WebXR experiences, where spatial audio becomes really important. There’s also always support and API improvements (if you like AudioBufferNode, you’re going to love AudioWorklet)
Conclusion
And that’s about it. Web Audio isn’t some black box, you can easily link it with whatever framework, or UI that you’ve built (whether you should is an entirely different question).
If anyone ever asks you “could you turn this SVG into a musical instrument?” you don’t have to stare blankly at them any more.
(function(a,c){var b=a.createElement(""script"");if(!(""noModule""in b)&&""on""+c in b){var d=!1;a.addEventListener(c,function(a){if(a.target===b)d=!0;else if(!a.target.hasAttribute(""nomodule"")||!d)return;a.preventDefault()},!0);b.type=""module"";b.src=""."";a.head.appendChild(b);b.remove()}})(document,""beforeload"");",2017,Ben Foxall,benfoxall,2017-12-17T00:00:00+00:00,https://24ways.org/2017/feeding-the-audio-graph/,code
40,Don’t Push Through the Pain,"In 2004, I lost my web career. In a single day, it was gone. I was in too much pain to use a keyboard, a Wacom tablet (I couldn’t even click the pen), or a trackball. Switching my mouse to use my left (non-dominant) hand only helped a bit; then that hand went, too. I tried all the easy-to-find equipment out there, except for expensive gizmos with foot pedals. I had tingling in my fingers—which, when I was away from the computer, would rhythmically move as if some other being controlled them. I worried about Parkinson’s because the movements were so dramatic. Pen on paper was painful. Finally, I discovered one day that I couldn’t even turn a doorknob.
The only highlight was that I couldn’t dust, scrub, or vacuum. We were forced to hire someone to come in once a week for an hour to whip through the house. You can imagine my disappointment.
My injuries had gradually slithered into my life without notice. I’d occasionally have sore elbows, or my wrist might ache for a day, or my shoulders feel tight. But nothing to keyboard home about. That’s the critical bit of news. One day, you’re pretty fine. The next day, you don’t have your job—or any job that requires the use of your hands and wrists.
I had to walk away from the computer for over four months—and partially for several months more. That’s right: no income. If I hadn’t found a gifted massage therapist, the right book of stretches, the equipment I should have been using all along, and learned how to pay attention to my body—even just a little bit more—I quite possibly wouldn’t be writing this article today. I wouldn’t be writing anything, anywhere.
Most of us have heard of (and even claimed to have read all of) Mihaly Csikszentmihalyi, author of Flow: The Psychology of Optimal Experience, who describes the state of flow—the place our minds go when we are fully engaged and in our element. This lovely state of highly focused activity is deeply satisfying, often creative, and quite familiar to many of us on the web who just can’t quit until the copy sings or the code is untangled or we get our highest score yet in Angry Birds. Our minds may enter that flow, but too often as our brains take flight, all else recedes. And we leave something very important behind.
Our bodies.
My body wasn’t made to make the same minute movements thousands of times a day, most days of the year, for decades, and neither was yours. The wear and tear sneaks up on you, especially if you’re the obsessive perfectionist that we all pretend not to be. Oh? You’re not obsessed? I wasn’t like this all the time, but I remember sitting across from my husband, eating dinner, and I didn’t hear a word he said. I’d left my brain upstairs in my office, where it was wrestling in a death match with the box model or, God help us all, IE 5.2. I was a writer, too, and I was having my first inkling that I was a content strategist. Work was exciting. I could sit up late, in the flow, fingers flying at warp speed. I could sit until those wretched birds outside mocked me with their damn, cheerful “Hurray, it’s morning!” songs. Suddenly, while, say, washing dishes, the one magical phrase that captured the essence of a voice or idea would pop up, and I would have mowed down small animals and toddlers to get to my computer and hammer out that website or article, to capture that thought before it escaped. Note my use of the word hammer. Sound at all familiar?
But where was my body during my work? Jaw jutting forward to see the screen, feet oddly positioned—and then left in place like chunks of marble—back unsupported, fingers pounding the keys, wrists and arms permanently twisted in unnatural angles that we thought were natural. And clicking. Clicking, clicking, clicking that mouse. Thumbing tiny keyboards on phones. A lethal little gesture for tiny little tendons. Though I was fine from, say 1997 to 2004, by the end of 2004 this behavior culminated in disaster. I had repetitive stress injuries, aka repetitive motion injuries. As the Apple site says, “A brief exposure to these conditions would not cause harm. But a prolonged exposure may, in some people, result in reduced ability to function.” I’ll say.
I frantically turned to people on lists and forums. “Try a track ball.” Already did that. “Try a tablet.” Worse. One person wrote, “I still come here once in a while and can type a couple sentences, but I’ve permanently got thoracic outlet syndrome and I’ll never work again.” Oh, beauteous web, oh, long-distance friends, farewell.
The Wrist Bone’s Connected to the Brain Bone
That variation on the old song tells part of the story. Most people (and many of their physicians) believe that tingling fingers and aching wrists MUST be carpel tunnel syndrome. Nope. If your neck juts forward, it tenses and stays tense the entire time you work in that position. Remember how your muscles felt after holding a landline phone with your neck tilted to one side for a long client meeting? Regrettable. Tensing your shoulders because your chair’s not designed properly puts you at risk for thoracic outlet syndrome, a career-killer if ever there was one. The nerves and tendons in your neck and shoulder refer down your arms, and muscles swell around nerves, causing pain and dysfunction. Your elbows have a tendon that is especially vulnerable to repetitive movements (think tennis elbow). Your wrists are performing something akin to a circus act with one thousand shows a day.
So, all the fine tendons and ligaments in your fingers have problems that may not start at your wrists at all. Though some people truly do have carpal tunnel syndrome, my finger and wrist problems weren’t solved by heavily massaging my fingers (though, that was helpful, too) or my wrists. They were fixed by work on my neck, upper back, shoulders, arms, and elbows. This explains why many people have surgery for carpal tunnel syndrome and just months later say, “What?! How can I possibly have it again? I had an operation!” Well, fellow buckaroo, you may never have had carpel tunnel syndrome. You may have had—or perhaps will have—one long disaster area from your neck to your fingertips.
How to Crawl Back
Before trying extreme measures, you may be able to function again even if you feel hopeless. I managed to heal, and so have others, but I’ll always be at risk.
As Jen Simmons, of The Web Ahead podcast and other projects told me, “It took a long time to injure myself. It took a long time to get back to where I was. My right arm between my elbow and wrist would start aching intermittently. Eventually, my arm even ached at night. I started each day with yesterday’s pain.” Simple measures, used consistently, helped her back.
1. Massage therapy
I don’t remember what the rest of the world is like, but in Portland, Oregon, we have more than one massage therapy college. (Of course we do.) I saw a former teacher at the most respected school. This is not your “It was all so soothing. Why, I fell asleep!” massage. This is “Holy crap, he’s grinding his elbow into my armpit!“ massage therapy, with the emphasis on therapy. I owe him everything. Make sure you have someone who really knows what they’re doing. Get many referrals. Try a question, “Does my psoas muscle affect my back?” If they can’t answer it, flee. Regularly see the one you choose and after a while, depending on how injured you are, you may be able to taper off.
2. Change your equipment
You may need to be hands-on with several pieces of equipment before you find the ones that don’t cause more pain. Many companies have restocking fees, charges to ship the equipment you want to return, and other retail atrocities. Always be sure to ask what the return policies are at any company before purchasing.
Mice
You may have more success than I did with equipment such as the Wacom tablet. Mine came with a pen, and it hurt to repetitively click it. Trackballs are another option but, for many, they are better at prevention than recovery. But let’s get to the really effective stuff. One of the biggest sources of pain is using your mouse. One major reason is that your hand and wrist are in a perpetually unnatural position and you’re also moving your arm quite a bit. Each time you move the mouse, it is placing stress on your neck, shoulders and arms, because you need to lift them slightly in order to move the mouse and you need to angle your wrist. You may also be too injured to use the trackpad all the time, and this mouse, the vertical mouse is a dandy preventative measure, too. Shaking up your patterns is a wise move. I have long fingers, not especially thin, yet the small size works best for me. (They have larger choices available.) What?! A sideways mouse? Yep. All the weight of your hand will be resting on it in the handshake position. Your forearms aren’t constantly twisting over hill and dale. You aren’t using any muscles in your wrist or hand. They are relaxing. You’ll adapt in a day, and oh, oh, what a relief it is.
Keyboards
I really liked doing business with the people at Kinesis-Ergo. (I’m not affiliated with them in any way.) They have the vertical mouse and a number of keyboards. The one that felt the most natural to me, and, once again, it only takes a day to adapt, is the Freestyle2 for the Mac. They have several options. I kept the keyboard halves attached to each other at first, and then spread them apart a little more. I recommend choosing one that slants and can separate. You can adjust the angle. For a little extra, they’ll make sure it’s all set up and ready to go for you. I’m guessing that some Googling will find you similar equipment, wherever you live.
Warning: if you use the ergonomic keyboards, you may have fewer USB ports. The laptop will be too far away to see unless you find a satisfactory setup using a stand. This is the perfect excuse for purchasing a humongous display.
You may not look cool while jetting coast to coast in your skinny jeans and what appears to be the old-time orthopedic shoe version of computing gear. But once you have rested and used many of these suggestions consistently, you may be able to use your laptop or other device in all its lovely sleekness during the trip.
Other doohickies
The Kinesis site and The Human Solution have a wide selection of ergonomic products: standing desks, ergonomically correct chairs, and, yes, even things with foot pedals. Explore!
3. Stop clicking, at least for a while
Use keyboard shortcuts, but use them slowly. This is not the time to show off your skillz. You’ll be sort of like a recovering alcoholic, in that you’ll be a recovering repetitive stress survivor for the rest of your life, once you really injure yourself. Always be vigilant. There’s also a bit of software sold by The Human Solution and other places, and it was my salvation. It’s called the McNib for Macs, and the Nib for PCs. (I’ve only used the McNib.) It’s for click-free mousing. I found it tricky to use when writing markup and code, but you may become quite adept at it. A little rectangle pops up on your screen, you mouse over it and choose, let’s say, “Double-click.” Until you change that choice, if you mouse over a link or anything else, it will double-click it for you. All you do is glide your mouse around. Awkward for a day or two, but you’ll pick it up quickly. Though you can use it all day for work, even if you just use this for browsing LOLcats or Gary Vaynerchuk’s YouTube videos, it will help you by giving your fingers a sweet break.
But here’s the sad news. The developer who invented this died a few years ago. (Yes, I used to speak to him on the phone.) While it is for sale, it isn’t compatible with Mac OS X Lion or anything subsequent. PowerPC strikes again. His site is still up. Demos for use with older software can be downloaded free at his old site, or at The Human Solution. Perhaps an enterprising developer can invent something that would provide this help, without interfering with patents. Rumor has it among ergonomic retailers (yes, I’m like a police dog sniffing my way to a criminal once I head down a trail) that his company was purchased by a company in China, with no update in sight.
4. Use built-in features
That little microphone icon that comes up alongside the keyboard on your iPhone allows you to speak your message instead of incessantly thumbing it. I believe it works in any program that uses the keyboard. It’s not Siri. She’s for other things, like having a personal relationship with an inanimate object. Apple even has a good section on ergonomics. You think I’m intense about this subject? To improve your repetitive stress, Apple doesn’t want you to use oral contraceptives, alcohol, or tobacco, to which I say, “Have as much sex, bacon, and chocolate as possible to make up for it.”
Apple’s info even has illustrations of things like a faucet dripping into what is labeled a bucket full of “TRAUMA.” Sounds like upgrading to Yosemite, but I digress.
5. Take breaks
If it’s a game or other non-essential activity, take a break for a month. Fine, now that I’ve called games non-essential, I suppose you’ll all unfollow me on Twitter.
6. Whether you are sore or not, do stretches throughout the day
This is a big one. Really big. The best book on the subject of repetitive stress injuries is Conquering Carpal Tunnel Syndrome and Other Repetitive Strain Injuries: A Self-Care Program by Sharon J. Butler. Don’t worry, most of it is illustrations. Pretend it’s a graphic novel.
I’m notorious for never reading instructions, and who on earth reads the introduction of a book, unless they wrote it? I wrote a book a long time ago, and I bet my house, husband, and life savings that my own parents never read the intro. Well, I did read the intro to this book, and you should, too. Stretching correctly, in a way that doesn’t further hurt you, that keeps you flexible if you aren’t injured, that actually heals you, calls for precision. Read and you’ll see. The key is to stretch just until you start to feel the stretch, even if that’s merely a tiny movement. Don’t force anything past that point. Kindly nurse yourself back to health, or nurture your still-healthy body by stretching. Over the following days, weeks, months, you’ll be moving well past that initial stretch point.
The book is brimming with examples. You only have to pick a few stretches, if this is too much to handle. Do it every single day. I can tell you some of the best ones for me, but it depends on the person. You’ll also discover in Butler’s book that areas that you think are the problem are sometimes actually adjacent to the muscle or tendon that is the source of the problem. Add a few stretches or two for that area, too.
But please follow the instructions in the introduction. If you overdo it, or perform some other crazy-ass hijinks, as I would be tempted to do, I am not responsible for your outcome. I give you fair warning that I am not a healthcare provider. I’m just telling you as a friend, an untrained one, at that, who has been through this experience.
7. Follow good habits
Develop habits like drinking lots of water (which helps with lactic acid buildup in muscles), looking away from the computer for twenty seconds every twenty to thirty minutes, eating right, and probably doing everything else your mother told you to do. Maybe this is a good time to bring up flossing your teeth, and going outside to play instead of watching TV. As your mom would say, “It’s a beautiful day outside, what are you kids doing in here?”
8. Speak instead of writing, if you can
Amber Simmons, who is very smart and funny, once tweeted in front of the whole world that, “@carywood is a Skype whore.” I was always asking people on Twitter if we could Skype instead of using iChat or exchanging emails. (I prefer the audio version so I don’t have to, you know, do something drastic like comb my hair.) Keyboarding is tough on hands, whether you notice it or not at the time, and when doing rapid-fire back-and-forthing with people, you tend to speed up your typing and not take any breaks. This is a hand-killer. Voice chats have made such a difference for me that I am still a rabid Skype whore. Wait, did I say that out loud?
Speak your text or emails, using Dragon Dictate or other software. In about 2005, accessibility and user experience design expert, Derek Featherstone, in Canada, and I, at home, chatted over the internet, each of us using a different voice-to-text program. The programs made so many mistakes communicating with each other that we began that sort of endless, tearful laughing that makes you think someone may need to call an ambulance. This type of software has improved quite a bit over the years, thank goodness. Lack of accessibility of any kind isn’t funny to Derek or me or to anyone who can’t use the web without pain.
9. Watch your position
For example, if you lift up your arms to use the computer, or stare down at your laptop, you’ll need to rearrange your equipment. The internet has a lot of information about ideal ergonomic work areas. Please use a keyboard drawer. Be sure to measure the height carefully so that even a tented keyboard, like the one I recommend, will fit. I also recommend getting the version of the Freestyle with palm supports. Just these two measures did much to help both Jen Simmons and me.
10. If you need to take anti-inflammatories, stop working
If you are all drugged up on ibuprofen, and pounding and clicking like mad, your body will not know when you are tired or injuring yourself. I don’t recommend taking these while using your computing devices. Perhaps just take it at night, though I’m not a fan of that category of medications. Check with your healthcare provider. At least ibuprofen is an anti-inflammatory, which may help you. In contrast, acetaminophen (paracetamol) only makes your body think it’s not in pain. Ice is great, as is switching back and forth between ice and heat. But again, if you need ice and ibuprofen you really need to take a major break.
11. Don’t forget the rest of your body
I’ve zeroed in on my personal area of knowledge and experience, but you may be setting yourself up for problems in other areas of your body. There’s what is known to bad writers as “a veritable cornucopia” of information on the web about how to help the rest of your body. A wee bit of research on the web and you’ll discover simple exercises and stretches for the rest of your potential catastrophic areas: your upper back, your lower back, your legs, ankles, and eyes. Do gentle stretches, three or four times a day, rather than powering your way through. Ease into new equipment such as standing desks. Stretch those newly challenged areas until your body adapts. Pay attention to your body, even though I too often forget mine.
12. Remember the children
Kids are using equipment to play highly addictive games or to explore amazing software, and if these call for repetitive motions, children are being set up for future injuries. They’ll grab hold of something, as parents out there know, and play it 3,742 times. That afternoon. Perhaps by the time they are adults, everything will just be holograms and mind-reading, but adult fingers and hands are used for most things in life, not just computing devices and phones with keyboards sized for baby chipmunks.
I’ll be watching you
Quickly now, while I (possibly) have your attention. Don’t move a muscle. Is your neck tense? Are you unconsciously lifting your shoulders up? How long since you stopped staring at the screen? How bright is your screen? Are you slumping (c’mon now, ‘fess up) and inviting sciatica problems? Do you have to turn your hands at an angle relative to your wrist in order to type? Uh-oh. That’s a bad one. Your hands, wrists, and forearms should be one straight line while keyboarding. Future you is begging you to change your ways. Don’t let your #ThrowbackThursday in 2020 say, “Here’s a photo from when I used to be able to do so many wonderful things that I can’t do now.” And, whatever you do, don’t try for even a nanosecond to push through the pain, or the next thing you know, you’ll be an unpaid extra in The Expendables 7.",2014,Carolyn Wood,carolynwood,2014-12-06T00:00:00+00:00,https://24ways.org/2014/dont-push-through-the-pain/,business
29,What It Takes to Build a Website,"In 1994 we lost Kurt Cobain and got the world wide web as a weird consolation prize. In the years that followed, if you’d asked me if I knew how to build a website I’d have said yes, I know HTML, so I know how to build a website. If you’d then asked me what it takes to build a website, I’d have had to admit that HTML would hardly feature.
Among the design nerdery and dev geekery it’s easy to think that the nuts and bolts of building a page just need to be multiplied up and Ta-da! There’s your website. That can certainly be true with weekend projects and hackery for fun. It works for throwing something together on GitHub or experimenting with ideas on your personal site. But what about working professionally on client projects?
The web is important, so we need to build it right.
It’s 2015 – your job involves people paying you money for building websites. What does it take to build a website and to do it right? What practices should we adopt to make really great, successful and professional web projects in 2015? I put that question to some friends and 24 ways authors to see what they thought.
Getting the tech right
Inevitably, it all starts with the technology. We work in a technical medium, after all. From Notepad and WinFTP through to continuous integration and deployment – how do you build sites?
Create a stable development environment
There’s little more likely to send a web developer into a wild panic and a client into a wild rage than making a new site live and things just not working. That’s why it’s important to have realistic development and staging environments that mimic the live server as closely as possible.
Are you in the habit of developing new sites right on the client’s server? Or maybe in a subfolder on your local machine? It’s time to reconsider.
Charlie Perrins writes:
Don’t work on a live server – this feels like one of those gear-changing moments for a developer’s growth. Build something that works just as well locally on your own machine as it does on a live server, and capture the differences in the code between the local and live version in a single config file. Ultimately, if you can get all the differences between environments down to a config level then you’ll be in a really good position to automate the deployment process at some point in the future.
Anything that creates a significant difference between the development and the live environments has the potential to cause problems you won’t know about until the site goes live – and at that point the problems are very public and very embarrassing, not to mention unprofessional.
A reasonable solution is to use a tool like MAMP PRO which enables you to set up an individual local website for each project you work on. Importantly, individual sites give you both consistency of paths between development and live, but also the ability to configure server options (like PHP versions and configuration, for example) to match the live site.
Better yet is to use a virtual machine, managed with a tool such as Vagrant. If you’re interested in learning more about that, we have an article on that subject later in the series.
Use source control
Trent Walton writes:
We use source control, and it’s become the centerpiece for how we handle collaboration, enhancements, and issues. It drives our process.
I’m hoping by now that you’re either using source control for all your work, or feeling a nagging guilt that you should be. Be it Git, Mercurial, Subversion (name your poison), a revision control system enables you to keep track of changes, revert anything that breaks, and keep rolling backups of your project.
The benefits only start there, and Charlie Perrins recommends using source control “not just as a personal backup of your code, but as a way to play nicely with other developers.“
Noting the benefits when collaborating with other developers, he adds:
Graduating from being the sole architect of your codebase to contributing to a shared codebase is a huge leap for a developer. Perhaps a practical way for people who tend to work on their own to do that would be to submit a pull request or a patch to an open source project or plugin.”
Richard Rutter of Clearleft sees clear advantages for the client, too. He recommends using source control “preferably in some sort of collaborative environment that you can open up or hand over to the client” – a feature found with hosted services such as GitHub.
If you’d like to hone your Git skills, Emma Jane Westby wrote Git for Grown-ups in last year’s 24 ways.
Don’t repeat, automate!
Tim Kadlec is a big proponent of automating your build process:
I’ve been hammering that home to every client I’ve had this year. It’s amazing how many companies don’t really have a formal build/deployment process in place. So many issues on the web (performance, accessibility, etc.) can be greatly improved just by having a layer of automation involved.
For example, graphic editing software spits out ridiculously bloated images. Very frequently, that’s what ends up getting put on a site. If you have a build process, you can have the compression automated and start seeing immediate gains for no effort. On a recent project, they were able to shave around 1.5MB from their site weight simply by automating compression.
Once you have your code in source control, some of that automation can be made easier. Brian Suda writes:
We have a few bash scripts that run on git commit: they compile the less, jslint and remove white-space, basically the 3 Cs, Compress, Concatenate, Combine. This is now part of our workflow without even realising it.
One great way to get started with a build process is to use a tool like Grunt, and a great way to get started with Grunt is to read Chris Coyier’s Grunt for People Who Think Things Like Grunt are Weird and Hard.
Tim reinforces:
Issues like [image compression] — or simple accessibility issues like alt tags on images — should never be able to hit a live server. If you can detect it, you can automate it. And if you can automate it, you can free up time for designers and developers to focus on more challenging — and interesting — problems.
A clear call to arms to tighten up and formalise development and deployment practices. The less that has to be done manually or is susceptible to change, the less that can go wrong when a site is built and deployed. Any procedures that are automated are no longer dependant on a single person’s knowledge, making it easier to build your team or just cope when someone important is out of the office or leaves.
If you’re interested in kicking the FTP habit and automating your site deployments, we have an article later in the series just for you.
Build systems, not sites
One big theme arising this year was that of building websites as systems, not as individual pages.
Brad Frost:
For me, teams making websites in 2015 shouldn’t be working on just-another-redesign redesign. People are realizing that in order to make stable, future-friendly, scalable, extensible web experiences they’re going to need to think more systematically. That means crafting deliberate and thoughtful design systems. That means establishing front-end style guides. That means killing the out-dated, siloed, assembly-line waterfall process and getting cross-disciplinary teams working together in meaningful ways. That means treating development as design. That means treating performance as design. That means taking the time out of the day to establish the big picture, rather than aimlessly crawling along quarter by quarter.
Designer and developer Jina Bolton also advocates the use of style guides, and recommends making the guide a project deliverable:
Consider adding on a style guide/UI library to your project as a deliverable for maintainability and thinking through all UI elements and components.
Val Head agrees: “build and maintain a style guide for each project” she wrote. On the subject of approaching a redesign, she added:
A UI inventory goes a long way to helping get your head around what a design system needs in the early stages of a redesign project.
So what about that old chestnut, responsive web design? Should we be making sites responsive by default? How about mobile first?
Richard Rutter:
Think mobile first unless you have a very good reason not to. Remember to take the client with you on this principle, otherwise it won’t work as a convincing piece of design.
Trent Walton adds:
The more you can test and sort of skew your perception for what is typical on the web, the better. 4k displays hooked up to 100Mbps connections can make one extremely unsympathetic.
The value of testing with real devices is something Ruth John appreciates. She wrote:
I still have my own small device lab at home, even though I work permanently for a well-established company (which has a LOT of devices at its disposal) – it just means I can get a good overview of how things are looking during development.
And speaking of systems, Mark Norman Francis recommends the use of measuring tools to aid the design process; “[U]se analytics and make decisions from actual data” he suggests, rather than relying totally on intuition.
Tim Kadlec adds a word on performance planning:
I think having a performance budget in place should now be a given on any project. We’ve proven pretty conclusively through a hundred and one case studies that performance matters. And over the last year or so, we’ve really seen a lot of great tools emerge to help track and enforce performance budgets. There’s not really a good excuse for not using one any more.
It’s clear that in the four years since Ethan Marcotte’s Responsive Web Design article the diversity of screen sizes, network connection speeds and input methods has only increased. New web projects should presume visitors will be using anything from a watch up to a big screen desktop display, and from being offline, through to GPRS, 3G and fast broadband.
Will it take more time to design and build for those constraints? Yes, it most likely will. If Internet Explorer is brave enough to ask to be your default browser, you can be brave enough to tell your client they need to build responsively.
Working collaboratively
A big part of delivering a successful website project is how we work together, both as a design team and a wider project team with the client.
Val Head recommends an open line of communication:
Keep conversations going. With clients, with teammates. Talking is so important with the way we work now. A good team conversation place, like Slack, is slowly becoming invaluable for me too.
Ruth John agrees:
We’ve recently opened up our lines of communication by using Slack. It has transformed the way we work. We’re easily more productive and collaborative on projects, as well as making it a lot easier for us all to work remotely (including freelancers).
She goes on to point out how tools can be combined to ease team communication without adding further complications:
We have a private GitHub organisation (which everyone who works with us is granted access to), which not only holds all our project code but also a team wiki. This has lots of information to get you set up within the team, as well as coding guidelines and best practices and other admin info, like contact numbers/emails for the team.
Small-A agile is also the theme of the day, with Mark Norman Francis suggesting an approach of “small iterations with constant feedback around individual features, not spec-it-all-first”. He also encourages you to review as you go, at each stage of the project:
Always reflect on what went well and what went badly, and how you can learn from that, even if not Doing Agile™. Ultimately “best practices” should come from learning lessons (both good and bad).
Richard Rutter echoes this, warning against working in isolation from the client for too long:
Avoid big reveals. Your engagement with the client should be participatory. In business no one likes surprises.
This experience rings true for Ruth John who recommends involving real users in the feedback loop, not just the client:
We also try and get feedback on what we’re building as soon and as often as we can with our stakeholders/clients and real users.
We should also remember that our role is to serve the client’s needs, not just bill them for whatever we can. Brian Suda adds:
Don’t sell clients on things they don’t need. We can spout a lot of jargon and scare clients into thinking you are a god. We can do things few can now, but you can’t rip people off because they are unknowledgeable.
But do clients know what they’re getting, even when they see it? Trent Walton has an interesting take:
We focus on prototypes over image-based comps at all costs, especially when meetings are involved. It’s much easier to assess a prototype, and too often with image-based comps, discussions devolve into how something might feel when actually live, or how a layout could change to fit a given viewport.
Val Head also likes to get work into the browser:
Sketch design ideas with any software you like, but get to the browser as soon as possible.
Beyond your immediate team, Emma Jane Westby has advice for looking further afield:
Invest time into building relationships within your (technical) community. You never know when you might be able to lend a hand; or benefit from someone who’s able to lend theirs.
And when things don’t go according to plan, Brian Suda has the following advice:
If something doesn’t work out, be professional and don’t burn bridges. It will always come back to you.
The best work comes from working collaboratively, not just as a team within an agency or department, but with the client and stakeholders too. If doing your job and chucking it over the fence ever worked, it certainly doesn’t fly any more. You can work in isolation, but doing really great work requires collaboration.
The business end
When you’re building sites professionally, every team member has to think about the business aspects. Estimating time, setting billing rates, and establishing deliverables are all part of the job.
In 2008, Andrew Clarke gave us the Contract Killer sample contract we could use to establish a working agreement for a web design project. Richard Rutter agrees that contracts are still an essential part of business:
They are there for both parties’ protection. Make sure you know what will happen if you decide you don’t want to work with the client any more (it happens) and, of course, what circumstances mean they can stop taking your services.
Having a contract is one thing, but does it adequately protect both you and the client? Emma Jane Westby adds:
Find a good IP lawyer/legal counsel. I routinely had an IP lawyer read all of my contracts to find loopholes I wouldn’t have noticed. I didn’t always change the contract, but at least I knew what might come back to bite me.
So, you have a contract in place, and know what the project is. Brian Suda recommends keeping track of time and making sure you bill fairly for the hours the project costs you:
If I go to a meeting and they are 15 minutes late, the billing clock has already started. They can’t expect me to be in the 1h meeting and not bill for the extra 15–30 minutes they wasted. It goes both ways too. You need to do your best to respect their deadlines and time frame – this is always hard to get right.
As ever, it’s good business to do good business. Perhaps we can at last shed the old image of web designers being snowboarding layabouts and demonstrate to clients that we care as much about conducting professional business as they do.
Time to review
It’s a lot to take in. Some of these ideas and practices will be familiar, others new and yet to be evaluated. The web moves at a fast pace, and we need to be constantly reexamining our tools, techniques and working practices. The most important thing is not to blindly adopt any and all suggestions, but to carefully look at what the benefits might be and decide how they apply to your work.
Could you benefit from more formalised development and deployment procedures? Would your design projects run more smoothly and have a longer maintainable life if you approached the solution as a componentised system rather than a series of pages? Are your teams structured in a way that enables the most fluid communication, or are there changes you could make? Are your billing procedures and business agreements serving you and your clients in the best way possible?
The new year is a good time to look at your working practices and see what can be improved, and maybe this time next year you’ll look back and think “thank goodness we don’t work like that any more”.",2014,Drew McLellan,drewmclellan,2014-12-01T00:00:00+00:00,https://24ways.org/2014/what-it-takes-to-build-a-website/,business
251,"The System, the Search, and the Food Bank","Imagine a warehouse, half the length of a football field, with a looped conveyer belt down the center.
On the belt are plastic bins filled with assortments of shelf-stable food—one may have two bags of potato chips, seventeen pudding cups, and a box of tissues; the next, a dozen cans of beets. The conveyer belt is ringed with large, empty cardboard boxes, each labeled with categories like “Bottled Water” or “Cereal” or “Candy.”
Such was the scene at my local food bank a few Saturdays ago, when some friends and I volunteered for a shift sorting donated food items. Our job was to fill the labeled cardboard boxes with the correct items nabbed from the swiftly moving, randomly stocked plastic bins.
I could scarcely believe my good fortune of assignments. You want me to sort things? Into categories? For several hours? And you say there’s an element of time pressure? Listen, is there some sort of permanent position I could be conscripted into.
Look, I can’t quite explain it: I just know that I love sorting, organizing, and classifying things—groceries at a food bank, but also my bookshelves, my kitchen cabinets, my craft supplies, my dishwasher arrangement, yes I am a delight to live with, why do you ask?
The opportunity to create meaning from nothing is at the core of my excitement, which is why I’ve tried to build a career out of organizing digital content, and why I brought a frankly frightening level of enthusiasm to the food bank. “I can’t believe they’re letting me do this,” I whispered in awe to my conveyer belt neighbor as I snapped up a bag of popcorn for the Snacks box with the kind of ferocity usually associated with birds of prey.
The jumble of donated items coming into the center need to be sorted in order for the food bank to be able to quantify, package, and distribute the food to those who need it (I sense a metaphor coming on). It’s not just a nice-to-have that we spent our morning separating cookies from carrots—it’s a crucial step in the process. Organization makes the difference between chaos and sense, between randomness and usefulness, whether we’re talking about donated groceries or—there it is—web content.
This happens through the magic of criteria matching. In order for us to sort the food bank donations correctly, we needed to know not only the categories we were sorting into, but also the criteria for each category. Does canned ravioli count as Canned Soup? Does enchilada sauce count as Tomatoes? Do protein bars count as Snacks? (Answers: yes, yes, and only if they are under 10 grams of protein or will expire within three months.)
Is X a Y? was the question at the heart of our food sorting—but it’s also at the heart of any information-seeking behavior. When we are organizing, or looking for, any kind of information, we are asking ourselves:
What is the criteria that defines Y?
Does X meet that criteria?
We don’t usually articulate it so concretely because it’s a background process, only leaping to consciousness when we encounter a stumbling block. If cans of broth flew by on the conveyer belt, it didn’t require much thought to place them in the Canned Soup box. Boxed broth, on the other hand, wasn’t allowed, causing a small cognitive hiccup—this X is NOT a Y—that sometimes meant having to re-sort our boxes.
On the web, we’re interested—I would hope—in reducing cognitive hiccups for our users. We are interested in making our apps easy to use, our websites easy to navigate, our information easy to access. After all, most of the time, the process of using the internet is one of uniting a question with an answer—Is this article from a trustworthy source? Is this clothing the style I want? Is this company paying their workers a living wage? Is this website one that can answer my question? Is X a Y?
We have a responsibility, therefore, to make information easy for our users to find, understand, and act on. This means—well, this means a lot of things, and I’ve got limited space here, so let’s focus on these three lessons from the food bank:
Use plain, familiar language. This advice seems to be given constantly, but that’s because it’s solid and it’s not followed enough. Your menu labels, page names, and headings need to reflect the word choice of your users. Think how much harder it would have been to sort food if the boxes were labeled according to nutritional content, grocery store aisle number, or Latin name. How much would it slow sorting down if the Tomatoes box were labeled Nightshades? It sounds silly, but it’s not that different from sites that use industry jargon, company lingo, acronyms (oh, yes, I’ve seen it), or other internally focused language when trying to provide wayfinding for users. Choose words that your audience knows—not only will they be more likely to spot what they’re looking for on your site or app, but you’ll turn up more often in search results.
Create consistency in all things. Missteps in consistency look like my earlier chicken broth example—changing up how something looks, sounds, or functions creates a moment of cognitive dissonance, and those moments add up. The names of products, the names of brands, the names of files and forms and pages, the names of processes and procedures and concepts—these all need to be consistently spelled, punctuated, linked, and referenced, no matter what section or level the user is in. If submenus are visible in one section, they should be visible in all. If calls-to-action are a graphic button in one section, they are the same graphic button in all. Every affordance, every module, every design choice sets up user expectations; consistency keeps those expectations afloat, making for a smoother experience overall.
Make the system transparent. By this, I do not mean that every piece of content should be elevated at all times. The horror. But I do mean that we should make an effort to communicate the boundaries of the digital space from any given corner within. Navigation structures operate just as much as a table of contents as they do a method of moving from one place to another. Page hierarchies help explain content relationships, communicating conceptual relevancy and relative importance. Submenus illustrate which related concepts may be found within a given site section. Take care to show information that conveys the depth and breadth of the system, rather than obscuring it.
This idea of transparency was perhaps the biggest challenge we experienced in food sorting. Imagine us volunteers as users, each looking for a specific piece of information in the larger system. Like any new visitor to a website, we came into the system not knowing the full picture. We didn’t know every category label around the conveyer belt, nor what criteria each category warranted.
The system wasn’t transparent for us, so we had to make it transparent as we went. We had to stop what we were doing and ask questions. We’d ask staff members. We’d ask more seasoned volunteers. We’d ask each other. We’d make guesses, and guess wrongly, and mess up the boxes, and correct our mistakes, and learn.
The more we learned, the easier the sorting became. That is, we were able to sort more quickly, more efficiently, more accurately. The better we understood the system, the better we were at interacting with it.
The same is true of our users: the better they understand digital spaces, the more effective they are at using them. But visitors to our apps and websites do not have the luxury of learning the whole system. The fumbling trial-and-error method that I used at the food bank can, on a website, drive users away—or, worse, misinform or hurt them.
This is why we must make choices that prioritize transparency, consistency, and familiarity. Our users want to know if X is a Y—well-sorted content can give them the answer.",2018,Lisa Maria Martin,lisamariamartin,2018-12-16T00:00:00+00:00,https://24ways.org/2018/the-system-the-search-and-the-food-bank/,content
308,How to Make a Chrome Extension to Delight (or Troll) Your Friends,"If you’re like me, you grew up drawing mustaches on celebrities. Every photograph was subject to your doodling wrath, and your brilliance was taken to a whole new level with computer programs like Microsoft Paint. The advent of digital cameras meant that no one was safe from your handiwork, especially not your friends. And when you finally got your hands on Photoshop, you spent hours maniacally giggling at your artistic genius.
But today is different. You’re a serious adult with important things to do and a reputation to uphold. You keep up with modern web techniques and trends, and have little time for fun other than a random Giphy on Slack… right?
Nope.
If there’s one thing 2016 has taught me, it’s that we—the self-serious, world-changing tech movers and shakers of the universe—haven’t changed one bit from our younger, more delightable selves.
How do I know? This year I created a Chrome extension called Tabby Cat and watched hundreds of thousands of people ditch productivity for randomly generated cats. Tabby Cat replaces your new tab page with an SVG cat featuring a silly name like “Stinky Dinosaur” or “Tiny Potato”. Over time, the cats collect goodies that vary in absurdity from fishbones to lawn flamingos to Raybans. Kids and adults alike use this extension, and analytics show the majority of use happens Monday through Friday from 9-5. The popularity of Tabby Cat has convinced me there’s still plenty of room in our big, grown-up hearts for fun.
Today, we’re going to combine the formula behind Tabby Cat with your intrinsic desire to delight (or troll) your friends, and create a web app that generates your friends with random objects and environments of your choosing. You can publish it as a Chrome extension to replace your new tab, or simply host it as a website and point to it with the New Tab Redirect extension.
Here’s a sneak peek at my final result featuring my partner, my cat, and I in cheerfully weird accessories. Your result will look however you want it to.
Along the way, we’ll cover how to build a Chrome extension that replaces the new tab page, and explore ways to program randomness into your work to create something truly delightful.
What you’ll need
Adobe Illustrator (or a similar illustration program to export PNG)
Some images of your friends
A text editor
Note: This can be as simple or as complex as you want it to be. Most of the application is pre-built so you can focus on kicking back and getting in touch with your creative side. If you want to dive in deeper, you’ll find ways to do it.
Getting started
Download a local copy of the boilerplate for today’s tutorial here, and open it in a text editor. Inside, you’ll find a simple web app that you can run in Chrome.
Open index.html in Chrome. You should see a grey page that says “Noname”.
Open template.pdf in Adobe Illustrator or a similar program that can export PNG. The file contains an artboard measuring 800px x 800px, with a dotted blue outline of a face. This is your template.
Note: We’re using Google Chrome to build and preview this application because the end-result is a Chrome extension. This means that the application isn’t totally cross-browser compatible, but that’s okay.
Step 1: Gather your friends
The first thing to do is choose who your muses are. Since the holidays are upon us, I’d suggest finding inspiration in your family.
Create your artwork
For each person, find an image where their face is pointed as forward as possible. Place the image onto the Artwork layer of the Illustrator file, and line up their face with the template. Then, rename the artboard something descriptive like face_bob. Here’s my crew:
As you can see, my use of the word “family” extends to cats. There’s no judgement here.
Notice that some of my photos don’t completely fill the artboard–that’s fine. The images will be clipped into ovals when they’re rendered in the application.
Now, export your images by following these steps:
Turn the Template layer off and export the images as PNGs.
In the Export dialog, tick the “Use Artboards” checkbox and enter the range with your faces.
Export at 72ppi to keep things running fast.
Save your images into the images/ folder in your project.
Add your images to config.js
Open scripts/config.js. This is where you configure your extension.
Add key value pairs to the faces object. The key should be the person’s name, and the value should be the filepath to the image.
faces: {
leslie: 'images/face_leslie.png',
kyle: 'images/face_kyle.png',
beep: 'images/face_beep.png'
}
The application will choose one of these options at random each time you open a new tab. This pattern is used for everything in the config file. You give the application groups of choices, and it chooses one at random each time it loads. The only thing that’s special about the faces object is that person’s name will also be displayed when their face is chosen.
Now, when you refresh the project in Chrome, you should see one of your friends along with their name, like this:
Congrats, you’re off and running!
Step 2: Add adjectives
Now that you’ve loaded your friends into the application, it’s time to call them names. This step definitely yields the most laughs for the least amount of effort.
Add a list of adjectives into the prefixes array in config.js. To get the words flowing, I took inspiration from ways I might describe some of my relatives during a holiday gathering…
prefixes: [
'Loving',
'Drunk',
'Chatty',
'Merry',
'Creepy',
'Introspective',
'Cheerful',
'Awkward',
'Unrelatable',
'Hungry',
...
]
When you refresh Chrome, you should see one of these words prefixed before your friend’s name. Voila!
Step 3: Choose your color palette
Real talk: I’m bad at choosing color palettes, so I have a trick up my sleeve that I want to share with you. If you’ve been blessed with the gift of color aptitude, skip ahead.
How to choose colors
To create a color palette, I start by going to a Coolors.co, and I hit the spacebar until I find a palette that I like. We need a wide gamut of hues for our palette, so lock down colors you like and keep hitting the spacebar until you find a nice, full range. You can use as many or as few colors as you like.
Copy these colors into your swatches in Adobe Illustrator. They’ll be the base for any illustrations you create later.
Now you need a set of background colors. Here’s my trick to making these consistent with your illustration palette without completely blending in. Use the “Adjust Palette” tool in Coolors to dial up the brightness a few notches, and the saturation down just a tad to remove any neon effect. These will be your background colors.
Add your background colors to config.js
Copy your hex codes into the bgColors array in config.js.
bgColors: [
'#FFDD77',
'#FF8E72',
'#ED5E84',
'#4CE0B3',
'#9893DA',
...
]
Now when you go back to Chrome and refresh the page, you’ll see your new palette!
Step 4: Accessorize
This is the fun part. We’re going to illustrate objects, accessories, lizards—whatever you want—and layer them on top of your friends.
Your objects will be categorized into groups, and one option from each group will be randomly chosen each time you load the page. Think of a group like “hats” or “glasses”. This will allow combinations of accessories to show at once, without showing two of the same type on the same person.
Create a group of accessories
To get started, open up Illustrator and create a new artboard out of the template. Think of a group of objects that you can riff on. I found hats to be a good place to start. If you don’t feel like illustrating, you can use cut-out images instead.
Next, follow the same steps as you did when you exported the faces. Here they are again:
Turn the Template layer off and export the images as PNGs.
In the Export dialog, tick the “Use Artboards” checkbox and enter the range with your hats.
Export at 72ppi to keep things running fast.
Save your images into the images/ folder in your project.
Add your accessories to config.js
In config.js, add a new key to the customProps object that describes the group of accessories that you just created. Its value should be an array of the filepaths to your images. This is my hats array:
customProps: {
hats: [
'images/hat_crown.png',
'images/hat_santa.png',
'images/hat_tophat.png',
'images/hat_antlers.png'
]
}
Refresh Chrome and behold, accessories!
Create as many more accessories as you want
Repeat the steps above to create as many groups of accessories as you want. I went on to make glasses and hairstyles, so my final illustrator file looks like this:
The last step is adding your new groups to the config object. List your groups in the order that you want them to be stacked in the DOM. My final output will be hair, then hats, then glasses:
customProps: {
hair: [
'images/hair_bowl.png',
'images/hair_bob.png'
],
hats: [
'images/hat_crown.png',
'images/hat_santa.png',
'images/hat_tophat.png',
'images/hat_antlers.png'
],
glasses: [
'images/glasses_aviators.png',
'images/glasses_monacle.png'
]
}
And, there you have it! Randomly generated friends with random accessories.
Feel free to go much crazier than I did. I considered adding a whole group of animals in celebration of the new season of Planet Earth, or even adding Sir David Attenborough himself, or doing a bit of role reversal and featuring the animals with little safari hats! But I digress…
Step 5: Publish it
It’s time to put this in your new tabs! You have two options:
Publish it as a Chrome extension in the Chrome Web Store.
Host it as a website and point to it with the New Tab Redirect extension.
Today, we’re going to cover Option #1 because I want to show you how to make the simplest Chrome extension possible. However, I recommend Option #2 if you want to keep your project private. Every Chrome extension that you publish is made publicly available, so unless your friends want their faces published to an extension that anyone can use, I’d suggest sticking to Option #2.
How to make a simple Chrome extension to replace the new tab page
All you need to do to make your project into a Chrome extension is add a manifest.json file to the root of your project with the following contents. There are plenty of other properties that you can add to your manifest file, but these are the only ones that are required for a new tab replacement:
{
""manifest_version"": 2,
""name"": ""Your extension name"",
""version"": ""1.0"",
""chrome_url_overrides"" : {
""newtab"": ""index.html""
}
}
To test your extension, you’ll need to run it in Developer Mode. Here’s how to do that:
Go to the Extensions page in Chrome by navigating to chrome://extensions/.
Tick the checkbox in the upper-right corner labelled “Developer Mode”.
Click “Load unpacked extension…” and select this project.
If everything is running smoothly, you should see your project when you open a new tab. If there are any errors, they should appear in a yellow box on the Extensions page.
Voila! Like I said, this is a very light example of a Chrome extension, but Google has tons of great documentation on how to take things further. Check it out and see what inspires you.
Share the love
Now that you know how to make a new tab extension, go forth and create! But wield your power responsibly. New tabs are opened so often that they’ve become a part of everyday life–just consider how many tabs you opened today. Some people prefer to-do lists in their tabs, and others prefer cats.
At the end of the day, let’s make something that makes us happy. Cheers!",2016,Leslie Zacharkow,lesliezacharkow,2016-12-08T00:00:00+00:00,https://24ways.org/2016/how-to-make-a-chrome-extension/,code
79,Responsive Images: What We Thought We Needed,"If you were to read a web designer’s Christmas wish list, it would likely include a solution for displaying images responsively. For those concerned about users downloading unnecessary image data, or serving images that look blurry on high resolution displays, finding a solution has become a frustrating quest.
Having experimented with complex and sometimes devilish hacks, consensus is forming around defining new standards that could solve this problem. Two approaches have emerged.
The element markup pattern was proposed by Mat Marquis and is now being developed by the Responsive Images Community Group. By providing a means of declaring multiple sources, authors could use media queries to control which version of an image is displayed and under what conditions:
Accessible text
A second proposal put forward by Apple, the srcset attribute, uses a more concise syntax intended for use with the element, although it could be compatible with the element too. This would allow authors to provide a set of images, but with the decision on which to use left to the browser:
Enter Scrooge
Men’s courses will foreshadow certain ends, to which, if persevered in, they must lead.
Ebenezer Scrooge
Given the complexity of this issue, there’s a heated debate about which is the best option. Yet code belies a certain truth. That both feature verbose and opaque syntax, I’m not sure either should find its way into the browser – especially as alternative approaches have yet to be fully explored.
So, as if to dampen the festive cheer, here are five reasons why I believe both proposals are largely redundant.
1. We need better formats, not more markup
As we move away from designs defined with fixed pixel values, bitmap images look increasingly unsuitable. While simple images and iconography can use scalable vector formats like SVG, for detailed photographic imagery, raster formats like GIF, PNG and JPEG remain the only suitable option.
There is scope within current formats to account for varying bandwidth but this requires cooperation from browser vendors. Newer formats like JPEG2000 and WebP generate higher quality images with smaller file sizes, but aren’t widely supported.
While it’s tempting to try to solve this issue by inventing new markup, the crux of it remains at the file level.
Daan Jobsis’s experimentation with image compression strengthens this argument. He discovered that by increasing the dimensions of a JPEG image while simultaneously reducing its quality, a smaller files could be produced, with the resulting image looking just as good on both standard and high-resolution displays.
This may be a hack in lieu of a more permanent solution, but it’s applied in the right place. Easy to accomplish with existing tools and without compatibility issues, it has few downsides. Further experimentation in this area should be encouraged, with standardisation efforts more helpful if focused on developing new image formats or, preferably, extending existing ones.
2. Art direction doesn’t belong in markup
A desired benefit of the markup pattern is to allow for greater art direction. For example, rather than scaling down images on smaller displays to the point that their content is hard to discern, we could present closer crops instead:
This can be achieved with CSS of course, although with a download penalty for those parts of an image not shown. This point may be negligible, however, since in the context of adaptable layouts, these hidden areas may end up being revealed anyway.
Art direction concerns design, not content. If we wish to maintain a separation of concerns, including presentation within our markup seems misguided.
3. The size of a display has little relation to the size of an image
By using media queries, the element allows authors to choose which characteristics of the screen or viewport to query for different images to be displayed.
In developing sites at Clearleft, we have noticed that the viewport is essentially arbitrary, with the size of an image’s containing element more important. For example, look at how this grid of images may adapt at different viewport widths:
As we build more modular systems, components need to be adaptable in and of themselves. There is a case to be made for developing more contextual methods of querying, rather than those based on attributes of the display.
4. We haven’t lived with the problem long enough
A key strength of the web is that the underlying platform can be continually iterated. This can also be problematic if snap judgements are made about what constitutes an improvement.
The early history of the web is littered with such examples, be it the perceived need for blinking text or inline typographic styling. To build a platform for the future, additions to it should be carefully considered. And if we want more consistent support across browsers, burdening vendors with an ever increasing list of features seems counterproductive.
Only once the need for a new feature is sufficiently proven, should we look to standardise it. Before we could declare hover effects, rounded corners and typographic styling in CSS, we used JavaScript as a polyfill. Sure, doing so was painful, but use cases were fully explored, and the CSS specification better reflected the needs of authors.
5. Images and the web aesthetic
The srcset proposal has emerged from a company that markets its phones as being able to browse the real – yet squashed down, tapped and zoomable – web. Perhaps Apple should make its own website responsive before suggesting how the rest of us should do so.
Converserly, while the proposal has the backing of a few respected developers and designers, it was born out of the work Mat Marquis and Filament Group did for the Boston Globe. As the first large-scale responsive design, this was a landmark project that ignited the responsive web design movement and proved its worth. But it was the first.
Its design shares a vernacular to that of contemporary newspaper websites, with a columnar, image-laden and densely packed layout. Compared to more recent examples – Quartz, The Next Web and the New York Times Skimmer – it feels out of step with the future direction of news sites. In seeking out a truer aesthetic for the web in which software interfaces have greater influence, we might discover that the need for responsive images isn’t as great as originally thought.
Building for the future
With responsive design, we’ve accepted the idea that a fully fluid layout, rather than a set of fixed layouts, is best suited to the web’s unpredictable nature. Current responsive image proposals are antithetical to this approach.
We need solutions that lack complexity, are device-agnostic and work within existing workflows. Any proposal that requires different versions of the same image to be created, is likely to have to acquiesce under the pressure of reality.
While it’s easy to get distracted about the size and quality of an image, and how we might choose to serve it, often the simplest solution is not to include it at all. After years of gluttonous design practice, in which fast connections and expansive display sizes were an accepted norm, we have got use to filling pages with needless images and countless items of page furniture.
To design more adaptable experiences, the presence of every element needs to be questioned, for its existence requires additional data to be downloaded or futher complexity within a design system. Conditional loading techniques mean that the inclusion of images is no longer a binary choice, but can instead appear in a progressively enhanced manner.
So here is my proposal. Instead of spending the next year worrying about responsive images, let’s embrace the constraints of the medium, and seek out new solutions that can work within them.",2012,Paul Lloyd,paulrobertlloyd,2012-12-11T00:00:00+00:00,https://24ways.org/2012/responsive-images-what-we-thought-we-needed/,code
121,Hide And Seek in The Head,"If you want your JavaScript-enhanced pages to remain accessible and understandable to scripted and noscript users alike, you have to think before you code. Which functionalities are required (ie. should work without JavaScript)? Which ones are merely nice-to-have (ie. can be scripted)? You should only start creating the site when you’ve taken these decisions.
Special HTML elements
Once you have a clear idea of what will work with and without JavaScript, you’ll likely find that you need a few HTML elements for the noscript version only.
Take this example: A form has a nifty bit of Ajax that automatically and silently sends a request once the user enters something in a form field. However, in order to preserve accessibility, the user should also be able to submit the form normally. So the form should have a submit button in noscript browsers, but not when the browser supports sufficient JavaScript.
Since the button is meant for noscript browsers, it must be hard-coded in the HTML:
When JavaScript is supported, it should be removed:
var checkJS = [check JavaScript support];
window.onload = function () {
if (!checkJS) return;
document.getElementById('noScriptButton').style.display = 'none';
}
Problem: the load event
Although this will likely work fine in your testing environment, it’s not completely correct. What if a user with a modern, JavaScript-capable browser visits your page, but has to wait for a huge graphic to load? The load event fires only after all assets, including images, have been loaded. So this user will first see a submit button, but then all of a sudden it’s removed. That’s potentially confusing.
Fortunately there’s a simple solution: play a bit of hide and seek in the :
var checkJS = [check JavaScript support];
if (checkJS) {
document.write('');
}
First, check if the browser supports enough JavaScript. If it does, document.write an extra