Tag Archives: html

Thumbnail

Designing A Textbox, Unabridged




Designing A Textbox, Unabridged

Shane Hudson



Ever spent an hour (or even a day) working on something just to throw the whole lot away and redo it in five minutes? That isn’t just a beginner’s code mistake; it is a real-world situation that you can easily find yourself in especially if the problem you’re trying to solve isn’t well understood to begin with.

This is why I’m such a big proponent of upfront design, user research, and creating often multiple prototypes — also known as the old adage of “You don’t know what you don’t know.” At the same time, it is very easy to look at something someone else has made, which may have taken them quite a lot of time, and think it is extremely easy because you have the benefit of hindsight by seeing a finished product.

This idea that simple is easy was summed up nicely by Jen Simmons while speaking about CSS Grid and Piet Mondrian’s paintings:

“I feel like these paintings, you know, if you look at them with the sense of like ‘Why’s that important? I could have done that.’ It’s like, well yeah, you could paint that today because we’re so used to this kind of thinking, but would you have painted this when everything around you was Victorian — when everything around you was this other style?”

I feel this sums up the feeling I have about seeing websites and design systems that make complete sense; it’s almost as if the fact they make sense means they were easy to make. Of course, it is usually the opposite; writing the code is the simple bit, but it’s the thinking and process that goes into it that takes the most effort.

With that in mind, I’m going to explore building a text box, in an exaggeration of situations many of us often find ourselves in. Hopefully, by the end of this article, we can all feel more emphatic to how the journey from start to finish is rarely linear.

A Comprehensive Guide To User Testing

So you think you’ve designed something that’s perfect, but your test tells you otherwise. Let’s explore the importance of user testing. Read more →

Brief

We all know that careful planning and understanding of the user need is important to a successful project of any size. We also all know that all too often we feel to need to rush to quickly design and develop new features. That can often mean our common sense and best practices are forgotten as we slog away to quickly get onto the next task on the everlasting to-do list. Rinse and repeat.

Today our task is to build a text box. Simple enough, it needs to allow a user to type in some text. In fact, it is so simple that we leave the task to last because there is so much other important stuff to do. Then, just before we pack up to go home, we smirk and write:

<input type="text">

There we go!

Oh wait, we probably need to hook that up to send data to the backend when the form is submitted, like so:

<input type="text" name="our_textbox">

That’s better. Done. Time to go home.

How Do You Add A New Line?

The issue with using a simple text box is it is pretty useless if you want to type a lot of text. For a name or title it works fine, but quite often a user will type more text than you expect. Trust me when I say if you leave a textbox for long enough without strict validation, someone will paste the entire of War and Peace. In many cases, this can be prevented by having a maximum amount of characters.

In this situation though, we have found out that our laziness (or bad prioritization) of leaving it to the last minute meant we didn’t consider the real requirements. We just wanted to do another task on that everlasting to-do list and get home. This text box needs to be reusable; examples of its usage include as a content entry box, a Twitter-style note box, and a user feedback box. In all of those cases, the user is likely to type a lot of text, and a basic text box would just scroll sideways. Sometimes that may be okay, but generally, that’s an awful experience.

Thankfully for us, that simple mistake doesn’t take long to fix:

<textarea name="our_textbox"></textarea>

Now, let’s take a moment to consider that line. A <textarea>: as simple as it can get without removing the name. Isn’t it interesting, or is it just my pedantic mind that we need to use a completely different element to add a new line? It isn’t a type of input, or an attribute used to add multi-line to an input. Also, the <textarea> element is not self-closing but an input is? Strange.

This “moment to consider” sent me time traveling back to October 1993, trawling through the depths of the www-talk mailing list. There was clearly much discussion about the future of the web and what “HTML+” should contain. This was 1993 and they were discussing ideas such as <input type="range"> which wasn’t available until HTML5, and Jim Davis said:

“Well, it’s far-fetched I suppose, but you might use HTML forms as part of a game playing interface.”

This really does show that the web wasn’t just intended to be about documents as is widely believed. Marc Andreessen suggested to have <input type="textarea"> instead of allowing new lines in the single-line text type, [saying]: (http://1997.webhistory.org/www.lists/www-talk.1993q4/0200.html)

“Makes the browser code cleaner — they have to be handled differently internally.”

That’s a fair reason to have <textarea> separate to text, but that’s still not what we ended up with. So why is <textarea> its own element?

I didn’t find any decision in the mailing list archives, but by the following month, the HTML+ Discussion Document had the <textarea> element and a note saying:

“In the initial design for forms, multi-line text fields were supported by the INPUT element with TYPE=TEXT. Unfortunately, this causes problems for fields with long text values as SGML limits the length of attributea literals. The HTML+ DTD allows for up to 1024 characters (the SGML default is only 240 characters!)”

Ah, so that’s why the text goes within the element and cannot be self-closing; they were not able to use an attribute for long text. In 1994, the <textarea> element was included, along with many others from HTML+ such as <option> in the HTML 2 spec.

Okay, that’s enough. I could easily explore the archives further but back to the task.

Styling A <textarea>

So we’ve got a default <textarea>. If you rarely use them or haven’t seen the browser defaults in a long time, then you may be surprised. A <textarea> (made almost purely for multi-line text) looks very similar to a normal text input except most browser defaults style the border darker, the box slightly larger, and there are lines in the bottom right. Those lines are the resize handle; they aren’t actually part of the spec so browsers all handle (pun absolutely intended) it in their own way. That generally means that the resize handle cannot be restyled, though you can disable resizing by setting resize: none to the <textarea>. It is possible to create a custom handle or use browser specific pseudo elements such as ::-webkit-resizer.


The default <code>&lt;textarea&gt;</code> looks very small with a grey border and three lines as a resize handle.


A default textarea with no styling (Large preview)

It’s important to understand the defaults, especially because of the resizing ability. It’s a very unique behavior; the user is able to drag to change the size of the element by default. If you don’t override the minimum and maximum sizes then the size could be as small as 9px × 9px (when I checked Chrome) or as large as they have patience to drag it. That’s something that could cause mayhem with the rest of the site’s layout if it’s not considered. Imagine a grid where <textarea> is in one column and a blue box is in another; the size of the blue box is purely decided by the size of the <textarea>.

Other than that, we can approach styling a <textarea> much the same as any other input. Want to change the grey around the edge into thick green dashes? Sure here you go: border: 5px dashed green;. Want to restyle the focus in which a lot of browsers have a slightly blurred box shadow? Change the outline — responsibly though, you know, that’s important for accessibility. You can even add a background image to your <textarea> if that interests you (I can think of a few ideas that would have been popular when skeuomorphic design was more celebrated).

Scope Creep

We’ve all experienced scope creep in our work, whether it is a client that doesn’t think the final version matches their idea or you just try to squeeze in a tiny tweak and end up taking forever to finish it. So I ( enjoying creating the persona of an exaggerated project manager telling us what we need to build) have decided that our <textarea> just is not good enough. Yes, it is now multi-line, and that’s great, and yes it even ‘pops’ a bit more with its new styling. Yet, it just doesn’t fit the very vague user need that I’ve pretty much just thought of now after we thought we were almost done.

What happens if the user puts in thousands of words? Or drags the resize handle so far it breaks the layout? It needs to be reusable, as we have already mentioned, but in some of the situations (such as a ‘Twittereqsue’ note taking box), we will need a limit. So the next task is to add a character limit. The user needs to be able to see how many characters they have left.

In the same way we started with <input> instead of <textarea>, it is very easy to think that adding the maxlength attribute would solve our issue. That is one way to limit the amount of characters the user types, it uses the browser’s built-in validation, but it is not able to display how many characters are left.

We started with the HTML, then added the CSS, now it is time for some JavaScript. As we’ve seen, charging along like a bull in a china shop without stopping to consider the right approaches can really slow us down in the long run. Especially in situations where there is a large refactor required to change it. So let’s think about this counter; it needs to update as the user types, so we need to trigger an event when the user types. It then needs to check if the amount of text is already at the maximum length.

So which event handler should we choose?

  • change
    Intuitively, it may make sense to choose the change event. It works on <textarea> and does what it says on the tin. Except, it only triggers when the element loses focus so it wouldn’t update while typing.
  • keypress
    The keypress event is triggered when typing any character, which is a good start. But it does not trigger when characters are deleted, so the counter wouldn’t update after pressing backspace. It also doesn’t trigger after a copy/paste.
  • keyup
    This one gets quite close, it is triggered whenever a key has been pressed (including the backspace button). So it does trigger when deleting characters, but still not after a copy/paste.
  • input
    This is the one we want. This triggers whenever a character is added, deleted or pasted.

This is another good example of how using our intuition just isn’t enough sometimes. There are so many quirks (especially in JavaScript!) that are all important to consider before getting started. So the code to add a counter that updates needs to update a counter (which we’ve done with a span that has a class called counter) by adding an input event handler to the <textarea>. The maximum amount of characters is set in a variable called maxLength and added to the HTML, so if the value is changed it is changed in only one place.

var textEl = document.querySelector('textarea')
var counterEl = document.querySelector('.counter')
var maxLength = 200
    
textEl.setAttribute('maxlength', maxLength)
textEl.addEventListener('input', (val) => 
var count = textEl.value.length
counterEl.innerHTML = $count/$maxLength
})

Browser Compatibility And Progressive Enhancement

Progressive enhancement is a mindset in which we understand that we have no control over what the user exactly sees on their screen, and instead, we try to guide the browser. Responsive Web Design is a good example, where we build a website that adjusts to suit the content on the particular size viewport without manually setting what each size would look like. It means that on the one hand, we strongly care that a website works across all browsers and devices, but on the other hand, we don’t care that they look exactly the same.

Currently, we are missing a trick. We haven’t set a sensible default for the counter. The default is currently “0/200” if 200 were the maximum length; this kind of makes sense but has two downsides. The first, it doesn’t really make sense at first glance. You need to start typing before it is obvious the 0 updates as you type. The other downside is that the 0 updates as you type, meaning if the JavaScript event doesn’t trigger properly (maybe the script did not download correctly or uses JavaScript that an old browser doesn’t support such as the double arrow in the code above) then it won’t do anything. A better way would be to think carefully beforehand. How would we go about making it useful when it is both working and when it isn’t?

In this case, we could make the default text be “200 character limit.” This would mean that without any JavaScript at all, the user would always see the character limit but it just wouldn’t feedback about how close they are to the limit. However, when the JavaScript is working, it would update as they type and could say “200 characters remaining” instead. It is a very subtle change but means that although two users could get different experiences, neither are getting an experience that feels broken.

Another default that we could set is the maxlength on the element itself rather than afterwards with JavaScript. Without doing this, the baseline version (the one without JS) would be able to type past the limit.

User Testing

It’s all very well testing on various browsers and thinking about the various permutations of how devices could serve the website in a different way, but are users able to use it?

Generally speaking, no. I’m consistently shocked by user testing; people never use a site how you expect them to. This means that user testing is crucial.

It’s quite hard to simulate a user test session in an article, so for the purposes of this article, I’m going to just focus on one point that I’ve seen users struggle with on various projects.

The user is happily writing away, gets to 0 characters remaining, and then gets stuck. They forget what they were writing, or they don’t notice that it had stopped typing.

This happens because there is nothing telling the user that something has changed; if they are typing away without paying much attention, then they can hit the maximum length without noticing. This is a frustrating experience.

One way to solve this issue is to allow overtyping, so the maximum length still counts for it to be valid when submitted but it allows the user to type as much as they want and then edit it before submission. This is a good solution as it gives the control back to the user.

Okay, so how do we implement overtyping? Instead of jumping into the code, let’s step through in theory. maxlength doesn’t allow overtyping, it just stops allowing input once it hits the limit. So we need to remove maxlength and write a JS equivalent. We can use the input event handler as we did before, as we know that works on paste, etc. So in that event, the handler would check if the user has typed more than the limit, and if so, the counter text could change to say “10 characters too many.” The baseline version (without the JS) would no longer have a limit at all, so a useful middle ground could be to add the maxlength to the element in the HTML and remove the attribute using JavaScript.

That way, the user would see that they are over the limit without being cut off while typing. There would still need to be validation to make sure it isn’t submitted, but that is worth the extra small bit of work to make the user experience far better.


An example showing “17 characters too many” in red text next to a <code>&lt;textarea&gt;</code>.


Allowing the user to overtype (Large preview)

Designing The Overtype

This gets us to quite a solid position: the user is now able to use any device and get a decent experience. If they type too much it is not going to cut them off; instead, it will just allow it and encourage them to edit it down.

There’s a variety of ways this could be designed differently, so let’s look at how Twitter handles it:


A screenshot from Twitter showing their textarea with overtyped text with a red background.


Twitter’s <textarea> (Large preview)

Twitter has been iterating its main tweet <textarea> since they started the company. The current version uses a lot of techniques that we could consider using.

As you type on Twitter, there is a circle that completes once you get to the character limit of 280. Interestingly, it doesn’t say how many characters are available until you are 20 characters away from the limit. At that point, the incomplete circle turns orange. Once you have 0 characters remaining, it turns red. After the 0 characters, the countdown goes negative; it doesn’t appear to have a limit on how far you can overtype (I tried as far as 4,000 characters remaining) but the tweet button is disabled while overtyping.

So this works the same way as our <textarea> does, with the main difference being the characters represented by a circle that updates and shows the number of characters remaining after 260 characters. We could implement this by removing the text and replacing it with an SVG circle.

The other thing that Twitter does is add a red background behind the overtyped text. This makes it completely obvious that the user is going to need to edit or remove some of the text to publish the tweet. It is a really nice part of the design. So how would we implement that? We would start again from the beginning.

You remember the part where we realized that a basic input text box would not give us multiline? And that a maxlength attribute would not give us the ability to overtype? This is one of those cases. As far as I know, there is nothing in CSS that gives us the ability to style parts of the text inside a <textarea>. This is the point where some people would suggest web components, as what we would need is a pretend <textarea>. We would need some kind of element — probably a div — with contenteditable on it and in JS we would need to wrap the overtyped text in a span that is styled with CSS.

What would the baseline non-JS version look like then? Well, it wouldn’t work at all because while contenteditable will work without JS, we would have no way to actually do anything with it. So we would need to have a <textarea> by default and remove that if JS is available. We would also need to do a lot of accessibility testing because while we can trust a <textarea> to be accessible relying on browser features is a much safer bet than building your own components. How does Twitter handle it? You may have seen it; if you are on a train and your JavaScript doesn’t load while going into a tunnel then you get chucked into a decade-old legacy version of Twitter where there is no character limit at all.

What happens then if you tweet over the character limit? Twitter reloads the page with an error message saying “Your Tweet was over the character limit. You’ll have to be more clever.” No, Twitter. You need to be more clever.

Retro

The only way to conclude this dramatization is a retrospective. What went well? What did we learn? What would we do differently next time or what would we change completely?

We started very simple with a basic textbox; in some ways, this is good because it can be all too easy to overcomplicate things from the beginning and an MVP approach is good. However, as time went on, we realized how important it is to have some critical thinking and to consider what we are doing. We should have known a basic textbox wouldn’t be enough and that a way of setting a maximum length would be useful. It is even possible that if we have conducted or sat in on user research sessions in the past that we could have anticipated the need to allow overtyping. As for the browser compatibility and user experiences across devices, considering progressive enhancement from the beginning would have caught most of those potential issues.

So one change we could make is to be much more proactive about the thinking process instead of jumping straight into the task, thinking that the code is easy when actually the code is the least important part.

On a similar vein to that, we had the “scope creep” of maxlength, and while we could possibly have anticipated that, we would rather not have any scope creep at all. So everybody involved from the beginning would be very useful, as a diverse multidisciplinary approach to even small tasks like this can seriously reduce the time it takes to figure out and fix all the unexpected tweaks.

Back To The Real World

Okay, so I can get quite deep into this made-up project, but I think it demonstrates well how complicated the most seemingly simple tasks can be. Being user-focussed, having a progressive enhancement mindset, and thinking things through from the beginning can have a real impact on both the speed and quality of delivery. And I didn’t even mention testing!

I went into some detail about the history of the <textarea> and which event listeners to use, some of this can seem overkill, but I find it fascinating to gain a real understanding of the subtleties of the web, and it can often help demystify issues we will face in the future.

Smashing Editorial
(ra, il)


See the original post – 

Designing A Textbox, Unabridged

Thumbnail

AMP: The Easiest Way to Build Lightning-Fast Mobile Pages is Almost Here

AMP is coming to the Unbounce Builder
If you run paid ads, chances are you have a mobile campaign or two (or two hundred) live right now. Whether we like it or not, most of us live tethered to our smartphones, relying on them to entertain us, keep us connected, and guide us to the nearest bike repair shop. And as such, behavior on mobile is shaping how marketers need to operate.

Over the last four years, we were inundated with messages declaring it was finally “the year of mobile”, so much so that it felt like our industry was crying wolf. Then in 2016, it finally happened: Mobile surpassed desktop in terms of both usage as well as Google search queries. Today, more than 60% of the world is accessing the internet through mobile devices, and that number is expected to climb.

Mobile surpasses desktop in October 2016

image via Tech Crunch.

The problem with this change? 2016 was two full years ago, and even though we were all warned to think mobile-first, advertisers forged ahead, bloating our responsive landing pages with massive high-res images, and animations. We were simply shrinking heavy content for small screen sizes. In turn, everyone’s mobile pages loaded turtle-slow (leaving visitors bouncing).

But we can’t ignore proper mobile experiences any more.

This year Google made pagespeed an official ranking factor for mobile search, introduced mobile speed score, and perhaps most important—they’re backing the Accelerated Mobile Pages open-source project: a means of developing web pages that load in (approximately) half a second! In short, the search giant’s putting their foot down and demanding a better, faster mobile web.

So how you can ensure your ads continue to appear in the SERP (considering load time is a factor)? And how can you give your landing pages a better shot to convert? Let’s walk through this need for speed together.

There’s still some lag

Unlike on social platforms, search advertisers have been a bit slow to jump onto the mobile bandwagon (no pun intended). Despite more searches happening on mobile, most advertisers are currently spending about an equal amount on desktop and mobile. In the 2018 State of Mobile report, Mary Meeker of Kleiner Perkins estimates that this gap represents about a seven billion dollar opportunity. In other words, the future is bright for mobile advertising and we’ll all likely adjust our spend accordingly very soon.

The question is, how will you prepare for this?

The shift to mobile advertising is underway

Image courtesy of slide 96 of the 2018 State of Mobile report.

It’s not about screen size, it’s about behavior

When mobile emerged as a hot topic, it was all about building mobile responsive, and then about building websites that were “mobile first.”

I distinctly remember being in the crowd at Unbounce’s first-ever Call to Action Conference back in 2014, when my marketing prayers were answered: Unbounce announced the ability to design mobile pages. But fast forward to today and we know that having a mobile version of your landing page is simply table stakes, as is splitting your campaign targeting by device.

Mobile responsive design was certainly a step forward, but now we can’t just reuse the same content across multiple devices.

To help illustrate why, just think about when you’re searching for something on your phone. You’re probably searching for something because you want it now. In the past two years alone, Google searches for “near me” (implying the intent to buy) have seen 500% growth.

When targeting these kinds of queries, you need to craft an experience that speaks to the searcher’s immediate need to find something locally—and fast. Every second your page lags, the more impatient the visitor.

Google Trends for search term "Near Me"

Looks like I’m not the only one looking for services “near me”. Image via Think With Google.

Personally, I have a bad habit of searching reviews and comparisons for an item while I’m in a store looking at the product in question. It’s hard to get me into a brick-and-mortar store in the first place, so you best believe I’m going to save myself a second trip, researching the best of the best, even in store aisles.

And I’m not alone: Between 2015-2017, the number of mobile searches including “best” on mobile increased by 80%, with consumers comparing products as simple as salt (likely right in the store or at point-of-purchase, like me):

image courtesy of Think With Google

Image courtesy of Think with Google.

Many of us shoppers are even completing the entire checkout process on-the-go. Last year, more than 40% of online purchases in the US were made on mobile during the months of November and October. So we’ve reached peak busy and are knocking out our Christmas shopping lists while we’re taking transit or waiting in line.

Why is this behavior so important?

Well, with so many using smartphones to search and browse on the go, slow-loading content is killing your potential conversions.

From a marketer’s perspective: for every second that a landing page takes to load, conversions drop by 12%—and 53% of smartphone users will abandon a page entirely if it takes more than three seconds to load.

These days, if your page isn’t anything but instant, visitors won’t stick around to convert, and you risk getting penalized by Google.

Maybe you’ve noticed the brand new Mobile Speed Score under the “landing page” tab in your account? This new column and ten-point score is another indication that Google is serious about mobile speed.

Example of Mobile Speed Score (image)

Have you been seeing any scores populate in your Mobile Speed Score column? Has it been helpful? Let us know in the comments!

Moreover, not all data connections are created equal

For those of us living in a metropolitan area, we spend a lot of our time jumping from our home wifi connections, to work, and back. For those times in between though, we’re in some kind of data limbo, with speeds ranging from 3G to LTE. A few times in my life, I’ve even gone to the dark place that is EDGE.

But what if I told you that 70% of the world is actually searching Google on a 3G connection or slower? Yup, you read that right. Even if you’re cruising on wifi or LTE, you might have potential customers living on the edge of data—or close to. On a 3G connection, the average mobile page takes a whopping 19 seconds to load, which means most of your visitors are abandoning your web pages before they’ve even seen them.

Curious how much traffic you’re actually losing to mobile pagespeed? Enter your landing page in this free Google tool to see the percentage.

So much for converting, hey!? You’ve paid for the ad click (sometimes quite handsomely, I might add), yet a portion of your visitors are leaving before they even see your content.

So it’s time to build faster landing pages somehow.

Not only will your visitors appreciate this, but Google will reward you. After all, they’re in the business of selling ads. As we mentioned, pagespeed is now factored into Landing Page Experience (one of the three core components of Quality Score). If you speed up your landing pages, you’ll see higher Quality Scores, an improved Ad Rank, and larger Search Impression Share (your ads will show more often).

You’ll basically give your landing pages a fighting chance to be seen and convert.

Faster mobile pages will produce a higher Google Ads Quality Score

AMPing up your pagespeed

Now, while you can implement a few manual fixes for faster landing pages—like compressing your images, reducing the amount of elements on your page, and even watching how many scripts are on there—even these methods produce diminishing returns at some point.

And this is where AMP can help.

If you haven’t heard of AMP (short for Accelerated Mobile Pages) it’s essentially a framework for coding simple, stripped down landing pages that load super fast (we’re talkin’ half-a-second-fast). It’s comprised of three elements: AMP HTML, AMP JS, and AMP Cache.

For us non-developers, AMP HTML is essentially a modified version of standard HTML, preventing us from creating pages that load slowly. Marketers can sometimes be guilty of designing beautiful pages with crisp, high-res images, parallax elements, and every tracking script under the sun. We love it, but that person looking for the closest place to fix their flat tire? Not so much.

AMP JS, on the other hand, ensures all of these elements load in an effective way. In my opinion, the third component, AMP Cache, is really AMP’s bread and butter. With AMP Cache, your landing page is cached by Google (or other third parties) so when a visitor requests your page from a platform like Google, it is served almost instantly. Which means the visitor isn’t stuck downloading every single image on their measly 3G connection before they can see your offer.

To implement AMP HTML and JS markup (to code a page from scratch), you’ll need to know a little bit more about web development, or know someone who does. AMP is only a few years old, and is an open-source project that is constantly being improved.

Every page on the framework also needs to pass through the AMP validator, which basically scans the page to make sure it adheres to all the requirements of AMP. If there are changes to the page that break validation, you might get stuck serving up your regular-ol’ too-slow mobile version.

Overall, it can become a burden on your development team if you’re constantly asking them to add a new AMP feature, keep pages validated, and build new ones for each campaign.

So we’re building AMP, the Unbounce way

I’ve always believed in keeping a strong relationship with the web developers at your company. They do amazing things and are typically working with a long backlog of website updates, some that you’ve probably requested yourself. And just like we don’t think you should be bugging developers for landing pages at all, we also want you to save them the headache of building AMP versions of all of your landing pages.

It’s been four years since I joined Unbounce’s mobile responsive beta at the Call to Action Conference, and later tomorrow I’ll be taking to the stage at CTAConf 2018 to share that we’ve entered closed beta for AMP in Unbounce. You’ll soon be able to create AMP landing pages in the same simple, pixel-perfect, drag and drop builder that you know and love. We hope you’re as excited as we are.

Build an AMP page in Unbounce in our beta

Get on the list: Unbounce’s AMP beta

If you’re ready to lower your bounce rates and stay BFF with your web devs, add your name to the early access list for the next phase of beta testing by following this link. You’ll be the very first to know as soon as we add spots or enter open beta, and you’ll be on your way to building lightning-fast mobile landing pages.

Are you as AMPed as we are? Let us know what you think about it in the comments!

More here – 

AMP: The Easiest Way to Build Lightning-Fast Mobile Pages is Almost Here

Thumbnail

Scroll Bouncing On Your Websites




Scroll Bouncing On Your Websites

William Lim



Scroll bouncing (also sometimes referred to as scroll ‘rubber-banding’, or ‘elastic scrolling’) is often used to refer to the effect you see when you scroll to the very top of a page or HTML element, or to the bottom of a page or element, on a device using a touchscreen or a trackpad, and empty space can be seen for a moment before the element or page springs back and aligns itself back to its top/bottom (when you release your touch/fingers). You can see a similar effect happen in CSS scroll-snapping between elements.

However, this article focuses on scroll bouncing when you scroll to the very top or very bottom of a web page. In other words, when the scrollport has reached its scroll boundary.

Collecting Data, The Powerful Way

Did you know that CSS can be used for collecting statistics? Indeed, there’s even a CSS-only approach for tracking UI interactions using Google Analytics. Read article →

A good understanding of scroll bouncing is very useful as it will help you to decide how you build your websites and how you want the page to scroll.

Scroll bouncing is undesirable if you don’t want to see fixed elements on a page move. Some examples include: when you want a header or footer to be fixed in a certain position, or if you want any other element such as a menu to be fixed, or if you want the page to scroll-snap at certain positions on scroll and you do not want any additional scrolling to occur at the very top or bottom of the page which will confuse visitors to your website. This article will propose some solutions to the problems faced when dealing with scroll bouncing at the very top or bottom of a web page.

My First Encounter With The Effect

I first noticed this effect when I was updating a website that I built a long time ago. You can view the website here. The footer at the bottom of the page was supposed to be fixed in its position at the bottom of the page and not move at all. At the same time, you were supposed to be able to scroll up and down through the main contents of the page. Ideally, it would work like this:

Scroll bouncing in Firefox on macOS
Scroll bouncing in Firefox on macOS. (Large preview)

It currently works this way in Firefox or on any browser on a device without a touchscreen or trackpad. However, at that time, I was using Chrome on a MacBook. I was scrolling to the bottom of the page using a trackpad when I discovered that my website was not working correctly. You can see what happened here:

Scroll bouncing in Chrome on macOS
Scroll bouncing in Chrome on macOS. (Large preview)

Oh no! This was not what was supposed to happen! I had set the footer’s position to be at the bottom of the page by setting its CSS position property to have a value of fixed. This is also a good time to revisit what position: fixed; is. According to the CSS 2.1 Specification, when a “box” (in this case, the dark blue footer) is fixed, it is “fixed with respect to the viewport and does not move when scrolled.” What this means is that the footer was not supposed to move when you scroll up and down the page. This was what worried me when I saw what was happening on Chrome.

To make this article more complete, I’ll show you how the page scrolls on both Mobile Edge, Mobile Safari and Desktop Safari below. This is different to what happens in scrolling on Firefox and Chrome. I hope this gives you a better understanding of how the exact same code currently works in different ways. It is currently a challenge to develop scrolling that works in the same way across different web browsers.

Scroll bouncing in Safari on macOS. A similar effect can be seen for Edge and Safari on iOS
Scroll bouncing in Safari on macOS. A similar effect can be seen for Edge and Safari on iOS. (Large preview)

Searching For A Solution

One of my first thoughts was that there would be an easy and a quick way to fix this issue on all browsers. What this means is that I thought that I could find a solution that would take a few lines of CSS code and that no JavaScript would be involved. Therefore, one of the first things I did, was to try to achieve this. The browsers I used for testing included Chrome, Firefox and Safari on macOS and Windows 10, and Edge and Safari on iOS. The versions of these browsers were the latest at the time of writing this article (2018).

HTML And CSS Only Solutions

Absolute And Relative Positioning

One of the first things I tried, was to use absolute and relative positioning to position the footer because I was used to building footers like this. The idea would be to set my web page to 100% height so that the footer is always at the bottom of the page with a fixed height, whilst the content takes up 100% minus the height of the footer and you can scroll through that. Alternatively, you can set a padding-bottom instead of using calc and set the body-container height to 100% so that the contents of the application do not overlap with the footer. The CSS code looked something like this:

html 
  width: 100%;
  height: 100%;
  overflow: hidden;
  position: relative;


body 
  width: 100%;
  margin: 0;
  font-family: sans-serif;
  height: 100%;
  overflow: hidden;


.body-container 
  height: calc(100% - 100px);
  overflow: auto;


.color-picker-main-container 
  width: 100%;
  font-size: 22px;
  padding-bottom: 10px;


footer 
  position: absolute;
  bottom: 0;
  height: 100px;
  width: 100%;

This solution works in almost the same way as the original solution (which was just position: fixed;). One advantage of this solution compared to that is that the scroll is not for the entire page, but for just the contents of the page without the footer. The biggest problem with this method is that on Mobile Safari, both the footer and the contents of the application move at the same time. This makes this approach very problematic when scrolling quickly:

Absolute and Relative Positioning
Absolute and Relative Positioning.

Another effect that I did not want was difficult to notice at first, and I only realized that it was happening after trying out more solutions. This was that it was slightly slower to scroll through the contents of my application. Because we are setting our scroll container’s height to 100% of itself, this hinders flick/momentum-based scrolling on iOS. If that 100% height is shorter (for example, when a 100% height of 2000px becomes a 100% height of 900px), the momentum-based scrolling gets worse. Flick/momentum-based scrolling happens when you flick on the surface of a touchscreen with your fingers and the page scrolls by itself. In my case, I wanted momentum-based scrolling to occur so that users could scroll quickly, so I stayed away from solutions that set a height of 100%.

Other Attempts

One of the solutions suggested on the web, and that I tried to use on my code, is shown below as an example.

html 
  width: 100%;
  position: fixed;
  overflow: hidden;


body 
  width: 100%;
  margin: 0;
  font-family: sans-serif;
  position: fixed;
  overflow: hidden;


.body-container 
  width: 100vw;
  height: calc(100vh - 100px);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;


.color-picker-main-container 
  width: 100%;
  font-size: 22px;
  padding-bottom: 10px;


footer 
  position: fixed;
  bottom: 0;
  height: 100px;
  width: 100%;

This code works on Chrome and Firefox on macOS the same way as the previous solution. An advantage of this method is that scroll is not restricted to 100% height, so momentum-based scrolling works properly. On Safari, however, the footer disappears:

Missing Footer on macOS Safari
Missing Footer on macOS Safari. (Large preview)

On iOS Safari, the footer becomes shorter, and there is an extra transparent (or white) gap at the bottom. Also, the ability to scroll through the page is lost after you scroll to the very bottom. You can see the white gap below the footer here:

Shorter Footer on iOS Safari
Shorter Footer on iOS Safari.

One interesting line of code you might see a lot is: -webkit-overflow-scrolling: touch;. The idea behind this is that it allows momentum-based scrolling for a given element. This property is described as “non-standard” and as “not on a standard track” in MDN documentation. It shows up as an “Invalid property value” under inspection in Firefox and Chrome, and it doesn’t appear as a property on Desktop Safari. I didn’t use this CSS property in the end.

To show another example of a solution you may encounter and a different outcome I found, I also tried the code below:

html 
  position: fixed;
  height: 100%;
  overflow: hidden;


body 
  font-family: sans-serif;
  margin: 0;
  width: 100vw; 
  height: 100vh;
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;


.color-picker-main-container 
  width: 100%;
  font-size: 22px;
  padding-bottom: 110px;


footer 
  position: fixed;

This actually works well across the different desktop browsers, momentum-based scrolling still works, and the footer is fixed at the bottom and does not move on desktop web browsers. Perhaps the most problematic part of this solution (and what makes it unique) is that, on iOS Safari the footer always shakes and distorts very slightly and you can see the content below it whenever you scroll.

Solutions With JavaScript

After trying out some initial solutions using just HTML and CSS, I gave some JavaScript solutions a try. I would like to add that this is something that I do not recommend you to do and would be better to avoid doing. From my experience, there are usually more elegant and concise solutions using just HTML and CSS. However, I had already spent a lot of time trying out the other solutions, I thought that it wouldn’t hurt to quickly see if there were some alternative solutions that used JavaScript.

Touch Events

One approach of solving the issue of scroll bouncing is by preventing the touchmove or touchstart events on the window or document. The idea behind this is that the touch events on the overall window are prevented, whilst the touch events on the content you want to scroll through are allowed. An example of code like this is shown below:

// Prevents window from moving on touch on older browsers.
window.addEventListener('touchmove', function (event) 
  event.preventDefault()
, false)

// Allows content to move on touch.
document.querySelector('.body-container').addEventListener('touchmove', function (event) 
  event.stopPropagation()
, false)

I tried many variations of this code to try to get the scroll to work properly. Preventing touchmove on the window made no difference. Using document made no difference. I also tried to use both touchstart and touchmove to control the scrolling, but these two methods also made no difference. I learned that you can no longer call event.preventDefault() this way for performance reasons. You have to set the passive option to false in the event listener:

// Prevents window from moving on touch on newer browsers.
window.addEventListener('touchmove', function (event) 
  event.preventDefault()
, passive: false)

Libraries

You may come across a library called “iNoBounce” that was built to “stop your iOS webapp from bouncing around when scrolling.” One thing to note when using this library right now to solve the problem I’ve described in this article is that it needs you to use -webkit-overflow-scrolling. Another thing to note is that the more concise solution I ended up with (which is described later) does a similar thing as it on iOS. You can test this yourself by looking at the examples in its GitHub Repository, and comparing that to the solution I ended up with.

Overscroll Behavior

After trying out all of these solutions, I found out about the CSS property overscroll-behavior. The overscroll-behavior CSS property was implemented in Chrome 63 on December 2017, and in Firefox 59 on March 2018. This property, as described in MDN documentation, “allows you to control the browser’s scroll overflow behavior — what happens when the boundary of a scrolling area is reached.” This was the solution that I ended up using.

All I had to do was set overscroll-behavior to none in the body of my website and I could leave the footer’s position as fixed. Even though momentum-based scrolling applied to the whole page, rather than the contents without the footer, this solution was good enough for me and fulfilled all of my requirements at that point in time, and my footer no longer bounced unexpectedly on Chrome. It is perhaps useful to note that Edge has this property flagged as under development now. overscroll-behavior can be seen as an enhancement if browsers do not support it yet.

Conclusion

If you don’t want your fixed headers or footers to bounce around on your web pages, you can now use the overscroll-behavior CSS property.

Despite the fact that this solution works differently in different browsers (bouncing of the page content still happens on Safari and Edge, whereas on Firefox and Chrome it doesn’t), it will keep the header or footer fixed when you scroll to the very top or bottom of a website. It is a concise solution and on all the browsers tested, momentum-based scrolling still works, so you can scroll through a lot of page content very quickly. If you are building a fixed header or footer on your web page, you can begin to use this solution.

Smashing Editorial
(rb, ra, yk, il)


Source:  

Scroll Bouncing On Your Websites

Thumbnail

The Holy Grail Of Reusable Components: Custom Elements, Shadow DOM, And NPM




The Holy Grail Of Reusable Components: Custom Elements, Shadow DOM, And NPM

Oliver Williams



For even the simplest of components, the cost in human-labour may have been significant. UX teams do usability testing. An array of stakeholders have to sign off on the design.

Developers conduct AB tests, accessibility audits, unit tests and cross-browser checks. Once you’ve solved a problem, you don’t want to repeat that effort. By building a reusable component library (rather than building everything from scratch), we can continuously utilize past efforts and avoid revisiting already solved design and development challenges.


A screenshot of Google’s material components website – showing various components.


Large preview

Building an arsenal of components is particularly useful for companies such as Google that own a considerable portfolio of websites all sharing a common brand. By codifying their UI into composable widgets, larger companies can both speed up development time and achieve consistency of both visual and user-interaction design across projects. There’s been a rise in interest in style guides and pattern libraries over the last several years. Given multiple developers and designers spread over multiple teams, large companies seek to attain consistency. We can do better than simple color swatches. What we need is easily distributable code.

Sharing And Reusing Code

Manually copy-and-pasting code is effortless. Keeping that code up-to-date, however, is a maintenance nightmare. Many developers, therefore, rely on a package manager to reuse code across projects. Despite its name, the Node Package Manager has become the unrivalled platform for front-end package management. There are currently over 700,000 packages in the NPM registry and billions of packages are downloaded every month. Any folder with a package.json file can be uploaded to NPM as a shareable package. While NPM is primarily associated with JavaScript, a package can include CSS and markup. NPM makes it easy to reuse and, importantly, update code. Rather than needing to amend code in myriad places, you change the code only in the package.

The Markup Problem

Sass and Javascript are easily portable with the use of import statements. Templating languages give HTML the same ability — templates can import other fragments of HTML in the form of partials. You can write the markup for your footer, for example, just once, then include it in other templates. To say there exists a multiplicity of templating languages would be an understatement. Tying yourself to just one severely limits the potential reusability of your code. The alternative is to copy-and-paste markup and to use NPM only for styles and javascript.

This is the approach taken by the Financial Times with their Origami component library. In her talk “Can’t You Just Make It More like Bootstrap?” Alice Bartlett concluded “there is no good way to let people include templates in their projects”. Speaking about his experience of maintaining a component library at Lonely Planet, Ian Feather reiterated the problems with this approach:

“Once they copy that code they are essentially cutting a version which needs to be maintained indefinitely. When they copied the markup for a working component it had an implicit link to a snapshot of the CSS at that point. If you then update the template or refactor the CSS, you need to update all versions of the template scattered around your site.”

A Solution: Web Components

Web components solve this problem by defining markup in JavaScript. The author of a component is free to alter markup, CSS, and Javascript. The consumer of the component can benefit from these upgrades without needing to trawl through a project altering code by hand. Syncing with the latest changes project-wide can be achieved with a terse npm update via terminal. Only the name of the component and its API need to stay consistent.

Installing a web component is as simple as typing npm install component-name into a terminal. The Javascript can be included with an import statement:

<script type="module">
import './node_modules/component-name/index.js';
</script>

Then you can use the component anywhere in your markup. Here is a simple example component that copies text to the clipboard.

See the Pen Simple web component demo by CSS GRID (@cssgrid) on CodePen.

A component-centric approach to front-end development has become ubiquitous, ushered in by Facebook’s React framework. Inevitably, given the pervasiveness of frameworks in modern front-end workflows, a number of companies have built component libraries using their framework of choice. Those components are reusable only within that particular framework.


A component from IBM’s Carbon Design System


A component from IBM’s Carbon Design System. For use in React applications only. Other significant examples of component libraries built in React include Atlaskit from Atlassian and Polaris from Shopify. (Large preview)

It’s rare for a sizeable company to have a uniform front-end and replatorming from one framework to another isn’t uncommon. Frameworks come and go. To enable the maximum amount of potential reuse across projects, we need components that are framework agnostic.


A screenshot from npmjs.com showing components that do that same thing built exclusively for particular javascript frameworks.


Searching for components via npmjs.com reveals a fragmented Javascript ecosystem. (Large preview)


A graph charting the popularity of frameworks over time. Ember, Knockout and Backbone have plunged in popularity, replaced by newer offerings.


The ever-changing popularity of frameworks over time. (Large preview)

“I have built web applications using: Dojo, Mootools, Prototype, jQuery, Backbone, Thorax, and React over the years…I would love to have been able to bring that killer Dojo component that I slaved over with me to my React app of today.”

Dion Almaer, Director of Engineering, Google

When we talk about a web component, we are talking about the combination of a custom element with shadow DOM. Custom Elements and shadow DOM are part of both the W3C DOM specification and the WHATWG DOM Standard — meaning web components are a web standard. Custom elements and shadow DOM are finally set to achieve cross-browser support this year. By using a standard part of the native web platform, we ensure that our components can survive the fast-moving cycle of front-end restructuring and architectural rethinks. Web components can be used with any templating language and any front-end framework — they’re truly cross-compatible and interoperable. They can be used everywhere from a WordPress blog to a single page application.


The Custom Elements Everywhere project by Rob Dodson documents the interoperability of web components with various client-side Javascript frameworks.


The Custom Elements Everywhere project by Rob Dodson documents the interoperability of web components with various client-side Javascript frameworks. React, the outlier here, will hopefully resolve these issues with React 17. (Large preview)

Making A Web Component

Defining A Custom Element

It’s always been possible to make up tag-names and have their content appear on the page.

<made-up-tag>Hello World!</made-up-tag>

HTML is designed to be fault tolerant. The above will render, even though it’s not a valid HTML element. There’s never been a good reason to do this — deviating from standardized tags has traditionally been a bad practice. By defining a new tag using the custom element API, however, we can augment HTML with reusable elements that have built-in functionality. Creating a custom element is much like creating a component in React — but here were extending HTMLElement.

class ExpandableBox extends HTMLElement 
      constructor() 
        super()
      
    }

A parameter-less call to super() must be the first statement in the constructor. The constructor should be used to set up initial state and default values and to set up any event listeners. A new custom element needs to be defined with a name for its HTML tag and the elements corresponding class:

customElements.define('expandable-box', ExpandableBox)

It’s a convention to capitalize class names. The syntax of the HTML tag is, however, more than a convention. What if browsers wanted to implement a new HTML element and they wanted to call it expandable-box? To prevent naming collisions, no new standardized HTML tags will include a dash. By contrast, the names of custom elements have to include a dash.

customElements.define('whatever', Whatever) // invalid
customElements.define('what-ever', Whatever) // valid

Custom Element Lifecycle

The API offers four custom element reactions — functions that can be defined within the class that will automatically be called in response to certain events in the lifecycle of a custom element.

connectedCallback is run when the custom element is added to the DOM.

connectedCallback() 
    console.log("custom element is on the page!")

This includes adding an element with Javascript:

document.body.appendChild(document.createElement("expandable-box")) //“custom element is on the page”

as well as simply including the element within the page with a HTML tag:

<expandable-box></expandable-box> // "custom element is on the page"

Any work that involves fetching resources or rendering should be in here.

disconnectedCallback is run when the custom element is removed from the DOM.

disconnectedCallback() 
    console.log("element has been removed")

document.querySelector("expandable-box").remove() //"element has been removed"

adoptedCallback is run when the custom element is adopted into a new document. You probably don’t need to worry about this one too often.

attributeChangedCallback is run when an attribute is added, changed, or removed. It can be used to listen for changes to both standardized native attributes like disabled or src, as well as any custom ones we make up. This is one of the most powerful aspects of custom elements as it enables the creation of a user-friendly API.

Custom Element Attributes

There are a great many HTML attributes. So that the browser doesn’t waste time calling our attributeChangedCallback when any attribute is changed, we need to provide a list of the attribute changes we want to listen for. For this example, we’re only interested in one.

static get observedAttributes() 
            return ['expanded']
        

So now our attributeChangedCallback will only be called when we change the value of the expanded attribute on the custom element, as it’s the only attribute we’ve listed.

HTML attributes can have corresponding values (think href, src, alt, value etc) while others are either true or false (e.g. disabled, selected, required). For an attribute with a corresponding value, we would include the following within the custom element’s class definition.

get yourCustomAttributeName() 
  return this.getAttribute('yourCustomAttributeName');

set yourCustomAttributeName(newValue) 
  this.setAttribute('yourCustomAttributeName', newValue);

For our example element, the attribute will either be true or false, so defining the getter and setter is a little different.

get expanded() 
  return this.hasAttribute('expanded')

        
// the second argument for setAttribute is mandatory, so we’ll use an empty string
set expanded(val) 
  if (val) 
    this.setAttribute('expanded', '');
  
  else 
    this.removeAttribute('expanded')
  
}

Now that the boilerplate has been dealt with, we can make use of attributeChangedCallback.

attributeChangedCallback(name, oldval, newval) 
  console.log(`the $name attribute has changed from $oldval to $newval!!`);
  // do something every time the attribute changes
}

Traditionally, configuring a Javascript component would have involved passing arguments to an init function. By utilising the attributeChangedCallback, its possible to make a custom element that’s configurable just with markup.

Shadow DOM and custom elements can be used separately, and you may find custom elements useful all by themselves. Unlike shadow DOM, they can be polyfilled. However, the two specs work well in conjunction.

Attaching Markup And Styles With Shadow DOM

So far, we’ve handled the behavior of a custom element. In regard to markup and styles, however, our custom element is equivalent to an empty unstyled <span>. To encapsulate HTML and CSS as part of the component, we need to attach a shadow DOM. It’s best to do this within the constructor function.

class FancyComponent extends HTMLElement 
        constructor() 
            super()
            var shadowRoot = this.attachShadow(mode: 'open')
            shadowRoot.innerHTML = `<h2>hello world!</h2>`
            }

Don’t worry about understanding what the mode means — its boilerplate you have to include, but you’ll pretty much always want open. This simple example component will just render the text “hello world”. Like most other HTML elements, a custom element can have children — but not by default. So far the above custom element we’ve defined won’t render any children to the screen. To display any content between the tags, we need to make use of a slot element.

shadowRoot.innerHTML = `
<h2>hello world!</h2>
<slot></slot>
`

We can use a style tag to apply some CSS to the component.

shadowRoot.innerHTML = 
`<style>
p 
color: red;

</style>
<h2>hello world!</h2>
<slot>some default content</slot>`

These styles will only apply to the component, so we are free to make use of element selectors without the styles affecting anything else of the page. This simplifies writing CSS, making naming conventions like BEM unnecessary.

Publishing A Component On NPM

NPM packages are published via the command line. Open a terminal window and move into a directory that you would like to turn into a reusable package. Then type the following commands into the terminal:

  1. If your project doesn’t already have a package.json, npm init will walk you through generating one.
  2. npm adduser links your machine to your NPM account. If you don’t have a preexisting account, it will create a new one for you.
  3. npm publish

NPM packages are published via the command line


Large preview

If all’s gone well, you now have a component in the NPM registry, ready to be installed and used in your own projects — and shared with the world.


An example of a component in the NPM registry, ready to be installed and used in your own projects.


Large preview

The web components API isn’t perfect. Custom elements are currently unable to include data in form submissions. The progressive enhancement story isn’t great. Dealing with accessibility isn’t as easy as it should be.

Although originally announced in 2011, browser support still isn’t universal. Firefox support is due later this year. Nevertheless, some high-profile websites (like Youtube) are already making use of them. Despite their current shortcomings, for universally shareable components they’re the singular option and in the future we can expect exciting additions to what they have to offer.

Smashing Editorial
(il, ra, yk)


See the original article here:

The Holy Grail Of Reusable Components: Custom Elements, Shadow DOM, And NPM

Advanced CSS Layouts With Flexbox and CSS Grid

Full-day workshop • June 28th
This workshop is designed for designers and developers who already have a good working knowledge of HTML and CSS. We will cover a range of CSS methods for achieving layout, from those you are safe to use right now even if you need to support older version of Internet Explorer through to things that while still classed as experimental, are likely to ship in browsers in the coming months.

Link – 

Advanced CSS Layouts With Flexbox and CSS Grid

Thumbnail

Making Avengers ID Card In HTML And CSS




Making Avengers ID Card In HTML And CSS

Kunal Sarkar



Let’s suppose Tony Stark would like to redesign the ID cards of the Avengers, and he needs our help to create them in HTML and CSS. So, how can we help? In this tutorial, we’ll be using Flexbox to create the desired layout while diving into nested flexboxes for some advanced layouts. We will also be using rounded as well as transparent borders to create sci-fi arcs in CSS, and then animating them by using CSS animations around the picture of the Avenger. Last but not least, we’ll be using the box-shadow and text-shadow properties to give our ID card a final sci-fi touch.

By the end of the tutorial, we will build a sci-fi animated Avengers ID card, and also learn the basics of Flexbox, nested Flexbox, CSS animations, borders, shadows, and many other frequently used CSS properties.

Here’s how our final Avengers ID card will look like:

See the Pen Avengers ID Card by Kunal Sarkar (@supersarkar) on CodePen.

Let’s get started!

Full-Page Background

We need a div that covers the entire screen. We will use this div as the background to place the ID card:

<div class="id-card-wrapper">
</div>

Let’s make the div cover the entire page and give a dark background:

body 
  margin:0px;

.id-card-wrapper 
  height: 100vh;
  width:100%;
  background-color: #122023;

Why use 100vh and not 100% for height?

If you look closely, you will notice that we used 100% for width, but 100vh for height. The vh unit stands for “viewport height”. It is a viewport unit, some other viewport units are: vw, vmin, and vmax.

So, why should we use 100vh instead of 100% for the height? Well, a % based dimension is relative to its parent element. So, if we set the height of the id-card-wrapper to 100%, that would mean it will make the height of id-card-wrapper cover 100% of the height of its parent element (which is the body element).

The problem is — by default — the body element doesn’t cover entire screen’s height. The width of the body element is by default 100% that’s why we can use width: 100% on id-card-wrapper, but since the height is not 100% by default the same won’t work for height.

Since a viewport unit is relative to the viewport, not the parent element, setting the height to 100vh will make the element cover entire height of the visible area (viewport), regardless of the parent’s dimensions.

Note: If you want to dive deeper into the viewport units, checkout this Fun with Viewport Units article on CSS-Tricks. One more thing, there are many ways to create a full page background, Chris Coyier lists them well in this post.

Why margin: 0px On Body?

The browsers by default display some margin around the body. If we don’t set this margin to 0, we will get a white gap around the id-card-wrapper div.

Centering Using Flexbox

There are many ways to center. Now that our full-page background is ready, let’s create the div that will contain our ID Card. We will put only “Test” as content, and build the layout first:

<div class="id-card-wrapper">
    <div class="id-card">
        Test
    </div>
</div>

And add some styles to it:

.id-card 
  border: 2px solid #0AE0DF;
  max-width: 30em;
  margin: auto;
  color: #fff;
  padding: 1em;

We are using the border property to give a 2px solid border of #0AE0DF color to the id-card element.

Since a “div” is a block element, it will cover the entire width of the parent element by default. But we don’t want it to go beyond 30em, so we’ll set the max-width property to 30em.

Wait, What Is em Again?

Here’s what W3C has to say about the “em” unit:

“The em is simply the font size. In an element with a 2in font, 1em thus means 2in.”

This means that if your browser has a default font size of 14px, then 30em will be equal to 30×14 = 420px.

But, why use em unit instead of px?

Look, the em unit is relative to the font size. Let’s suppose you are using a browser with 14px default font size. Now if someone views your project from another browser that has 16px as default font size, then guess what would happen?

The content inside will need more space, but your div has a fixed width, i.e. the content will either spill out or break the layout.

It’s always a good idea to have dimensions that scale along with the content, instead of fixing it to arbitrary pixels.

Why Doesn’t margin: auto Center The div Vertically?**

We already know that we can center a block element horizontally using margin: auto, but it doesn’t work for vertical centering.


Screenshot of a horizontally centered element


Auto margin centers the element horizontally

What if I told you that margin: auto works vertically, too? Actually, in normal layout mode, it doesn’t. But in new layout modes like Flexbox, the margin: auto works for vertical centering, too. Go ahead and make the id-card-wrapper a flexbox to see it yourself:

.id-card-wrapper 
  height: 100vh;
  width:100%;
  background-color: #122023;
  display: flex;

Output:


Screenshot of a horizontally and vertically centered element


Auto margin centers the element horizontally and vertically if the element is a flex-item

As you can see, our id-card div is now centered horizontally and vertically. We simply set display: flex on the id-card-wrapper div. When you set display: flex to an element, that element becomes a flex-container and its child elements become flex-items. Check out “Basic Concepts Of Flexbox” on MDN.

Okay, this did center our element, but why did it lose its width? The id-card div is a block element, and since block elements are by default 100% wide, why did the div lose this block level behavior when it became a flex-item?

Actually, it hasn’t lost its block behavior. What’s happening is, as soon as the div comes into the flexbox context, the flexbox algorithm notes that the div doesn’t have any width property set to it (we are giving it only max-width), and then it sets the initial width to 0.

We can change this behavior by explicitly defining the initial width of the element using the [flex-basis](https://developer.mozilla.org/en-US/docs/Web/CSS/flex-basis) property, like this:

.id-card 
  flex-basis: 100%;
  border: 2px solid #0AE0DF;
  max-width: 30em;
  margin: auto;
  color: #fff;
  padding: 1em;

And now the result looks just as expected:


Screenshot of a flex-item set with flex-basis set to 100%


The initial width of the flex-item set to 100% using “flex-basis”

Nested Flexboxes

Now our id-card div is ready for content. Let’s create a profile-row div and two sections in it dp and desc. The dp div will contain the profile photo of the Avenger while the desc div will contain the description of that Avenger:

<div class="id-card-wrapper">
    <div class="id-card">
        <div class="profile-row">
            <div class="dp">
                Test
            </div>
            <div class="desc">
                Test desc
            </div>
        </div>
    </div>
</div>

We know that the id-card div is a flex-item, but the div we just created inside id-card (the profile-row div) isn’t a flex-item. Yes, only the direct decedents of the flex-containers become flex-items, but not the grandchildren.

Therefore, profile-row is a normal div, and we will make it a flex-container by setting display: flex to it. This will make its child elements, dp and desc, flex-items:

.profile-row 
  display: flex;

Now we can use the flex-basis property to make the dp div 33.3% wide and the desc div 66.6% wide:

.profile-row .dp 
  flex-basis: 33.3%;

.profile-row .desc 
  flex-grow: 66.6%;

Here’s what we get:


Screenshot of two flex-items in a row with 33.3% and 66.6% width


We can define how much space the elements would occupy using the “flex-basis” property.

Profile Image

For the profile image, we will use a cute Iron Man picture for Stark’s ID card (download it here). Include the image using img tag inside the dp div:

<div class="id-card-wrapper">
    <div class="id-card">
        <div class="profile-row">
            <div class="dp">
                <img src="img/iron-man-dp.jpg">
            </div>
            <div class="desc">
                Test desc
            </div>
        </div>
    </div>
</div>

And give some styles to it:

.profile-row .dp img 
  max-width: 100%;
  border-radius: 50%;

.profile-row .desc 
  padding: 1em;

We set max-width: 100% for the img element because the img element by default displays the image in its original resolution.

If the image is 500px×500px then it will be displayed in that dimension. But we don’t want that. Instead, we want the image to be only as wide as the dp div, that’s why we set its max-width to 100%.

Also, we set the border-radius property to 50%. We are doing this to display the image as a circle:


Screenshot of Iron Man rounded image with demo text


We don’t make the img element a flex-item, but rather put it inside a flex-item.

Making Arcs In CSS

Eventually, Tony visits us while we’re still working on this ID card, and says that this doesn’t look sci-fi enough. Alright, no problem. Let’s make it more sci-fi. We can make two arcs rotate around the image by inserting the first arc dp-arc-inner inside the dp element:

<div class="id-card-wrapper">
    <div class="id-card">
        <div class="profile-row">
            <div class="dp">
                <div class="dp-arc-inner"></div>
                <img src="img/iron-man-dp.jpg">
            </div>
            <div class="desc">
                Test desc
            </div>
        </div>
    </div>
</div>

Position it in CSS:

.profile-row .dp 
  flex-basis: 33.3%;
  position: relative;

.profile-row .dp img 
  max-width: 100%;
  border-radius: 50%;
  display: block;

.profile-row .dp .dp-arc-inner 
  position: absolute;
  width: 100%;
  height: 100%;
  border: 6px solid #0AE0DF;
  top: -6px;
  left: -6px;

We want the arc div to overlap on the dp div. The only problem is that elements don’t overlap in HTML. However, if we set the position of an element as absolute then that element is taken out of the normal flow of the document and we can set its position as we desire.

The default positioning of HTML elements is static. We set position: absolute on dp-arc-inner to make it absolutely positioned. Now we can use left, top, bottom, and right properties to set its position.

One caution: The left, top, bottom, and right properties are relative the first parent element in the hierarchy which is “relatively” positioned. That’s why we’ve set position: relative on the dp div. If we don’t do this, the left, top, bottom, and right properties will be set respectively to the screen, not the dp element.

One more thing: we are setting display: block on the img element. Why? Because img elements are inline-block by default, and inline-block elements display a tiny gap on its sides and bottom.

This gap generally doesn’t cause any problem, but a little gap around the image in our case will offset the arc’s position. So we set the img element as block element.

Next, let’s make the dp-arc-inner div look like an arc:

.profile-row .dp .dp-arc-inner 
  position: absolute;
  width: 100%;
  height: 100%;
  border: 6px solid transparent;
  border-top-color: #0AE0DF;
  border-radius: 50%;
  top: -6px;
  left: -6px;

What we are doing is, instead of setting the border for all the sides with #0AE0DF color, we are setting all the sides as transparent, and then giving only the top border the color #0AE0DF. Then we set the border-radius: 50% to make it round:


Screenshot of Iron Man’s rounded image surrounded with an arc covering it


The negative margins offsets the width of the border we gave to the arc

Okay, let’s create one more arc, dp-arc-outer:

<div class="id-card-wrapper">
    <div class="id-card">
        <div class="profile-row">
            <div class="dp">
                <div class="dp-arc-outer"></div>
                <div class="dp-arc-inner"></div>
                <img src="img/iron-man-dp.jpg">
            </div>
            <div class="desc">
                Test desc
            </div>
        </div>
    </div>
</div>

And style it the same way:

.profile-row .dp .dp-arc-outer 
  position: absolute;
  width: calc(100% + 12px);
  height: calc(100% + 12px);
  border: 6px solid transparent;
  border-bottom-color: #0AE0DF;
  border-radius: 50%;
  top: -12px;
  left: -12px;

Wow, what’s that calc thing there?

Calc is a CSS function that calculates the mathematical expression given to it. Look, we had the inner arc with width and height of 100% and a border of 6px, right? That makes the inner arc’s total width 6px + 100% + 6px.

Now if we want the outer arc to be bigger than the inner arc then we need some way to make it 100% + 12px wide. This is where the calc() function comes to the rescue.

Also, notice that we are using border-bottom-color for this arc since we want the arc to display on the bottom.

Output:


Screenshot of Iron Man’s rounded image surrounded with two arcs covering it


The calc function adds 12px to create the 6px gap between the arc and the image

Animating The Arcs

Now that our arcs are ready, let’s make them rotate around the image. We can do this with the help of CSS animations.

Any animation requires three basic things:

  1. The start state of the animation,
  2. The end state of the animation,
  3. How long it should take to go from start to end state (speed of the animation).

We can provide these data in CSS like this:

.profile-row .dp .dp-arc-inner 
  position: absolute;
  width: 100%;
  height: 100%;
  border: 6px solid transparent;
  border-top-color: #0AE0DF;
  border-radius: 50%;
  top: -6px;
  left: -6px;

  animation-duration: 2s;
  animation-name: rotate-clock;

@keyframes rotate-clock 
  from 
    transform: rotate(0deg);
  
  to 
    transform: rotate(360deg);
  
}

We use @keyframes to define the animation. The from and to keywords are used to set the start and end state of the animation.

In the start state, we are rotating the arc 0-degree using transform: rotate(0deg), and in the end state we are rotating the arc 360-degree using transform: rotate(360deg).

To use this animation on an element, we need to give the name of the animation (rotate-clock in our case) to the animation-name property of that element. That’s what we are doing with animation-name: rotate-clock .

We also need to know how long it should take the animation to complete. We can do this by setting animation-duration property to 2s.

See the Pen Avengers ID Card – 1 by Kunal Sarkar (@supersarkar) on CodePen.

You will notice two problems in the output. One, the arc is rotated only one time, we want it to keep rotating, and two, the animation is not linear. The animation is fast at beginning and end, we want it to rotate with same speed throughout the animation.

To solve these problems, we will use the animation-iteration-count property to keep the animation repate itself infinite times, and animation-timing-function property to get a linear animation:

.profile-row .dp .dp-arc-inner 
  position: absolute;
  width: 100%;
  height: 100%;
  border: 6px solid transparent;
  border-top-color: #0AE0DF;
  border-radius: 50%;
  top: -6px;
  left: -6px;

  animation-duration: 2s;
  animation-name: rotate-clock;
  animation-iteration-count: infinite;
  animation-timing-function: linear;

See the Pen Avengers ID Card – 2 by Kunal Sarkar (@supersarkar) on CodePen.

Okay, the inner arc is now rotating as expected. Now let’s animate the outer arc in the same way, but in the opposite direction:

.profile-row .dp 
  flex-basis: 33.3%;
  position: relative;
  margin: 24px;

.profile-row .dp .dp-arc-outer 
  position: absolute;
  width: calc(100% + 12px);
  height: calc(100% + 12px);
  border: 6px solid transparent;
  border-bottom-color: #0AE0DF;
  border-radius: 50%;
  top: -12px;
  left: -12px;

  animation-duration: 2s;
  animation-name: rotate-anticlock;
  animation-iteration-count: infinite;
  animation-timing-function: linear;

@keyframes rotate-anticlock 
  from 
    transform: rotate(0deg);
  
  to 
    transform: rotate(-360deg);
  
}

We only changed the to state for the outer arc. Instead of rotating it a positive 360 degree, we rotated it a negative 360 degree, to get an anti-clockwise animation.

Note that we also added 24px margin to the .dp so that it doesn’t get too congested. Here’s what our result looks like now:

See the Pen Avengers ID Card – 3 by Kunal Sarkar (@supersarkar) on CodePen.

Using A Sci-Fi Google Font

Tony visits again, and this time he is happy with where we are heading. Only one thing though: he asks to use a sci-fi font.

Not a problem. Let’s use the Orbitron font from Google Fonts. Google Fonts gives a wealth of fonts for free and this particular font fits our requirement quite well.

Click on “Select this Font”:


Screenshot of Google Font page of Orbitron font


You will see the “Select this font” link once you visit the Google font link

A popover will appear at the bottom. Click on it. You will get two codes: the <link> code to copy into your HTML, and the font-family code to use in your CSS:


Screenshot of Google Font page of Orbitron font with the font selected


When you click the “Select this font” link a pop-up will be displayed with link and “font-family” code of that font

Copy the <link> code into your HTML file just above the line where you are including your stylesheet.

Now let’s add some details of Iron Man inside the desc div:

<div class="id-card-wrapper">
    <div class="id-card">
        <div class="profile-row">
            <div class="dp">
                <div class="dp-arc-outer"></div>
                <div class="dp-arc-inner"></div>
                <img src="img/iron-man-dp.jpg">
            </div>
            <div class="desc">
                <h1>Tony Stark</h1>
                <p>Strength: Ironman Suit</p>
                <p>Weakness: None</p>
                <p>Known as: Iron Man</p>
            </div>
        </div>
    </div>
</div>

In our CSS, we will use the font-family code from Google Fonts to set the font of “desc” div:

.profile-row .desc 
  font-family: 'Orbitron', sans-serif;
  color: #a4f3f2;

.profile-row .desc h1 
  margin: 0px;

Wait a sec, why are we setting the margin of h1 to 0?

All the heading elements (h1, h2, h3, h4, and h5) are displayed with some margin around it by the browsers. This is usually not a problem, but we don’t want the top and bottom gaps around the heading elements right now. That’s why we zeroed the margin for h1 element.

Let’s have a look at the output:

See the Pen Avengers ID Card – 4 by Kunal Sarkar (@supersarkar) on CodePen.

Oh no! What happened?

What’s happening is, the height of the dp div is increasing.

Normally, if the content in the desc div is of more height than the height of the dp div then nothing happens to the dp div. However, in flexbox layout, the height of the dp div will also increase along with the height of the desc div.

We don’t want the dp div to increase in height with the desc div, and we can do that by using [align-self](https://developer.mozilla.org/en-US/docs/Web/CSS/align-self) sub-property of flexbox:

.profile-row .dp 
  flex-basis: 33.3%;
  align-self: center;
  position: relative;
  margin: 24px;

See the Pen Avengers ID Card – 5 by Kunal Sarkar (@supersarkar) on CodePen.

The align-self: center makes the dp div to center keeping its height the same.

Adding Glow

Let’s add some glow.

But wait, CSS doesn’t have any glow property.

No problem, it does have the [text-shadow](https://developer.mozilla.org/en-US/docs/Web/CSS/text-shadow) property. If we give a bright color to the shadow, the shadow will look like it’s glowing:

.profile-row .desc 
  font-family: 'Orbitron', sans-serif;
  color: #d3f8f7;
  text-shadow: 0px 0px 4px #12a0a0;
  letter-spacing: 1px;

In the text-shadow property, the first value, 0px, is the x-offset, how much the shadow is away from text in the x-direction. The second value, 0px, is the y-offset, telling us how much the shadow is away from the text in the y-direction. The third value, 4px, is the amount of blur you want to give to the shadow. The fourth value, #12a0a0, is the color of the shadow.

Note, we also added a 1px space between the letters of text using the [letter-spacing](https://developer.mozilla.org/en-US/docs/Web/CSS/letter-spacing) property because the text was looking a bit congested.

Next, let’s add some shadow to the ID card and the image:

.id-card 
  flex-basis: 100%;
  max-width: 30em;
  border: 1px solid rgb(97, 245, 245);
  margin: auto;
  color: #fff;
  padding: 1em;
  background-color: #0D2C36;
  box-shadow: 0px 0px 3px 1px #12a0a0, inset 0px 0px 3px 1px #12a0a0;

.profile-row .dp img 
  max-width: 100%;
  border-radius: 50%;
  display: block;
  box-shadow: 0px 0px 4px 3px #12a0a0;

The text-shadow property gives shadow to the text, and the [box-shadow](https://developer.mozilla.org/en-US/docs/Web/CSS/box-shadow) property gives shadow to the elements.

The first three values for box-shadow are the same as text-shadow: x-offset, y-offset, and blur. The fourth value is how much you want the shadow to spread, and the fifth value is the color of the shadow.

Notice how we are giving two shadows, outer and inner, to the id-card div in a single line:

box-shadow: 0px 0px 3px 1px #12a0a0, inset 0px 0px 3px 1px #12a0a0;

The first five values create an outer shadow. Then the “inset” keyword specifies that the next five values are for inside shadow. We separate both with a ,.

See the Pen Avengers ID Card by Kunal Sarkar (@supersarkar) on CodePen.

The Avengers ID card is ready. Yay!

Wrapping Up

In this tutorial, we learned an effective way of making a full-page background, and centering elements with Flexbox and auto margins. We saw the basic usage of Flexbox and nested Flexboxes to make single dimension layouts.

If you want to dive deeper into Flexbox, check out “A Complete Guide to Flexbox” by Chris Coyier at CSS-Tricks. If you are more of a video learner, then you will enjoy the free 20 video course by Web Bos at Flexbox.io.

We also used CSS animations and the rotate transform to make animated arcs, however, we used a limited number of CSS properties and values. If you want to explore more about CSS animations then you will love this detailed MDN guide.

Finally, the glowing elements gave our ID card a unique sci-fi look. We used the “box-shadow” property to give the glow to our elements. Sometimes manually setting the values of the “box-shadow” property becomes cumbersome. Use CSSmatic’s Box Shadow CSS Generator to easily generate box shadows.

Smashing Editorial
(rb, ra, il)


Original post: 

Making Avengers ID Card In HTML And CSS

Thumbnail

Managing SVG Interaction With The Pointer Events Property




Managing SVG Interaction With The Pointer Events Property

Tiffany Brown



Try clicking or tapping the SVG image below. If you put your pointer in the right place (the shaded path) then you should have Smashing Magazine’s homepage open in a new browser tab. If you tried to click on some white space, you might be really confused instead.

See the Pen Amethyst by Tiffany Brown (@webinista) on CodePen.

This is the dilemma I faced during a recent project that included links within SVG images. Sometimes when I clicked the image, the link worked. Other times it didn’t. Confusing, right?

I turned to the SVG specification to learn more about what might be happening and whether SVG offers a fix. The answer: pointer-events.

Not to be confused with DOM (Document Object Model) pointer events, pointer-events is both a CSS property and an SVG element attribute. With it, we can manage which parts of an SVG document or element can receive events from a pointing device such as a mouse, trackpad, or finger.

A note about terminology: “pointer events” is also the name of a device-agnostic, web platform feature for user input. However, in this article — and for the purposes of the pointer-events property — the phrase “pointer events” also includes mouse and touch events.

Outside Of The Box: SVG’s “Shape Model”

Using CSS with HTML imposes a box layout model on HTML. In the box layout model, every element generates a rectangle around its contents. That rectangle may be inline, inline-level, atomic inline-level, or block, but it’s still a rectangle with four right angles and four edges. When we add a link or an event listener to an element, the interactive area matches the dimensions of the rectangle.

Note: Adding a clip-path to an interactive element alters its interactive bounds. In other words, if you add a hexagonal clip-path path to an a element, only the points within the clipping path will be clickable. Similarly, adding a skew transformation will turn rectangles into rhomboids.

SVG does not have a box layout model. You see, when an SVG document is contained by an HTML document, within a CSS layout, the root SVG element adheres to the box layout model. Its child elements do not. As a result, most CSS layout-related properties don’t apply to SVG.

So instead, SVG has what I’ll call a ‘shape model’. When we add a link or an event listener to an SVG document or element, the interactive area will not necessarily be a rectangle. SVG elements do have a bounding box. The bounding box is defined as: the tightest fitting rectangle aligned with the axes of that element’s user coordinate system that entirely encloses it and its descendants. But initially, which parts of an SVG document are interactive depends on which parts are visible and/or painted.

Painted vs. Visible Elements

SVG elements can be “filled” but they can also be “stroked”. Fill refers to the interior of a shape. Stroke refers to its outline.

Together, “fill” and “stroke” are painting operations that render elements to the screen or page (also known as the canvas). When we talk about painted elements, we mean that the element has a fill and/or a stroke. Usually, this means the element is also visible.

However, an SVG element can be painted without being visible. This can happen if the visible attribute value or CSS property is hidden or when display is none. The element is there and occupies theoretical space. We just can’t see it (and assistive technology may not detect it).

Perhaps more confusingly, an element can also be visible — that is, have a computed visibility value of visible — without being painted. This happens when elements lack both a stroke and a fill.

Note: Color values with alpha transparency (e.g. rgba(0,0,0,0)) do not affect whether an element is painted or visible. In other words, if an element has an alpha transparent fill or stroke, it’s painted even if it can’t be seen.

Knowing when an element is painted, visible, or neither is crucial to understanding the impact of each pointer-events value.

All Or None Or Something In Between: The Values

pointer-events is both a CSS property and an SVG element attribute. Its initial value is auto, which means that only the painted and visible portions will receive pointer events. Most other values can be split into two groups:

  1. Values that require an element to be visible; and
  2. Values that do not.

painted, fill, stroke, and all fall into the latter category. Their visibility-dependent counterparts — visiblePainted, visibleFill, visibleStroke and visible — fall into the former.

The SVG 2.0 specification also defines a bounding-box value. When the value of pointer-events is bounding-box, the rectangular area around the element can also receive pointer events. As of this writing, only Chrome 65+ supports the bounding-box value.

none is also a valid value. It prevents the element and its children from receiving any pointer events. The pointer-events CSS property can be used with HTML elements too. But when used with HTML, only auto and none are valid values.

Since pointer-events values are better demonstrated than explained, let’s look at some demos.

Here we have a circle with a fill and a stroke applied. It’s both painted and visible. The entire circle can receive pointer events, but the area outside of the circle cannot.

See the Pen Visible vs painted in SVG by Tiffany Brown (@webinista) on CodePen.

Disable the fill, so that its value is none. Now if you try to hover, click, or tap the interior of the circle, nothing happens. But if you do the same for the stroke area, pointer events are still dispatched. Changing the fill value to none means that this area visible, but not painted.

Let’s make a small change to our markup. We’ll add pointer-events="visible" to our circle element, while keeping fill=none.

See the Pen How adding pointer-events: all affects interactivity by Tiffany Brown (@webinista) on CodePen.

Now the unpainted area encircled by the stroke can receive pointer events.

Augmenting The Clickable Area Of An SVG Image

Let’s return to the image from the beginning of this article. Our “amethyst” is a path element, as opposed to a group of polygons each with a stroke and fill. That means we can’t just add pointer-events="all" and call it a day.

Instead, we need to augment the click area. Let’s use what we know about painted and visible elements. In the example below, I’ve added a rectangle to our image markup.

See the Pen Augmenting the click area of an SVG image by Tiffany Brown (@webinista) on CodePen.

Even though this rectangle is unseen, it’s still technically visible (i.e. visibility: visible). Its lack of a fill, however, means that it is not painted. Our image looks the same. Indeed it still works the same — clicking white space still doesn’t trigger a navigation operation. We still need to add a pointer-events attribute to our a element. Using the visible or all values will work here.

See the Pen Augmenting the click area of an SVG image by Tiffany Brown (@webinista) on CodePen.

Now the entire image can receive pointer events.

Using bounding-box would eliminate the need for a phantom element. All points within the bounding box would receive pointer events, including the white space enclosed by the path. But again: pointer-events="bounding-box" isn’t widely supported. Until it is, we can use unpainted elements.

Using pointer-events When Mixing SVG And HTML

Another case where pointer-events may be helpful: using SVG inside of an HTML button.

See the Pen Ovxmmy by Tiffany Brown (@webinista) on CodePen.

In most browsers — Firefox and Internet Explorer 11 are exceptions here — the value of event.target will be an SVG element instead of our HTML button. Let’s add pointer-events="none" to our opening SVG tag.

See the Pen How pointer-events: none can be used with SVG and HTML by Tiffany Brown (@webinista) on CodePen.

Now when users click or tap our button, the event.target will refer to our button.

Those well-versed in the DOM and JavaScript will note that using the function keyword instead of an arrow function and this instead of event.target fixes this problem. Using pointer-events="none" (or pointer-events: none; in your CSS), however, means that you don’t have to commit that particular JavaScript quirk to memory.

Conclusion

SVG supports the same kind of interactivity we’re used to with HTML. We can use it to create charts that respond to clicks or taps. We can create linked areas that don’t adhere to the CSS and HTML box model. And with the addition of pointer-events, we can improve the way our SVG documents behave in response to user interaction.

Browser support for SVG pointer-events is robust. Every browser that supports SVG supports the property for SVG documents and elements. When used with HTML elements, support is slightly less robust. It isn’t available in Internet Explorer 10 or its predecessors, or any version of Opera Mini.

We’ve just scratched the surface of pointer-events in this piece. For a more in-depth, technical treatment, read through the SVG Specification. MDN (Mozilla Developer Network) Web Docs offers more web developer-friendly documentation for pointer-events, complete with examples.

Smashing Editorial
(rb, ra, yk, il)


Link to original:

Managing SVG Interaction With The Pointer Events Property

Thumbnail

Contributing To MDN Web Docs




Contributing To MDN Web Docs

Rachel Andrew



MDN Web Docs has been documenting the web platform for over twelve years and is now a cross-platform effort with contributions and an Advisory Board with members from Google, Microsoft and Samsung as well as those representing Firefox. Something that is fundamental to MDN is that it is a huge community effort, with the web community helping to create and maintain the documentation. In this article, I’m going to give you some pointers as to the places where you can help contribute to MDN and exactly how to do so.

If you haven’t contributed to an open source project before, MDN is a brilliant place to start. Skills needed range from copyediting, translating from English to other languages, HTML and CSS skills for creating Interactive Examples, or an interest in browser compatibility for updating Browser Compatibility data. What you don’t need to do is to write a whole lot of code to contribute. It’s very straightforward, and an excellent way to give back to the community if you have ever found these docs useful.

Contributing To The Documentation Pages

The first place you might want to contribute is to the MDN docs themselves. MDN is a wiki, so you can log in and start to help by correcting or adding to any of the documentation for CSS, HTML, JavaScript or any of the other parts of the web platform covered by MDN.

To start editing, you need to log in using GitHub. As is usual with a wiki, any editors of a page are listed, and this section will use your GitHub username. If you look at any of the pages on MDN contributors are listed at the bottom of the page, the below image shows the current contributors to the page on CSS Grid Layout.


A list showing names of people who contributed to this page


The contributors to the CSS Grid Layout page. (Large preview)

What Might You Edit?

Things that you might consider as an editor are fixing obvious typos and grammatical errors. If you are a good proofreader and copyeditor, then you may well be able to improve the readability of the docs by fixing any spelling or other errors that you spot.

You might also spot a technical error, or somewhere the specs have changed and where an update or clarification would be useful. With the huge range of web platform features covered by MDN and the rate of change, it is very easy for things to get out of date, if you spot something – fix it!

You may be able to use some specific knowledge you have to add additional information. For example, Eric Bailey has been adding Accessibility Concerns sections to many pages. This is a brilliant effort to highlight the things we should be thinking about when using a certain thing.


A screenshot of the Accessibility Concerns section


This section highlights the things we should be aware of when using background-color. (Large preview)

Another place you could add to a page is in adding “See also” links. These could be links to other parts of MDN, or to external resources. When adding external resources, these should be highly relevant to the property, element or technique being described by that document. A good candidate would be a tutorial which demonstrates how to use that feature, something which would give a reader searching for information a valuable next step.

How To Edit A Document?

Once you are logged in you will see a link to Edit on pages in MDN, clicking this will take you into a WYSIWYG editor for editing content. Your first few edits are likely to be small changes, in which case you should be able to follow your nose and edit the text. If you are making extensive edits, then it would be worth taking a look at the style guide first. There is also a guide to using the WYSIWYG Editor.

After making your edit, you can Preview and then Publish. Before publishing it is a good idea to explain what you added and why using the Revision Comment field.


Screenshot of this field in the edit form


Add a comment using the Revision Comment field. (Large preview)

Language Translations

Those of us with English as a first language are incredibly fortunate when it comes to information on the web, being able to get pretty much all of the information that we could ever want in our own language. If you are able to translate English language pages into other languages, then you can help to translate MDN Web Docs, making all of this information available to more people.


A screenshot showing the drop-down translations list


Translations available for the background-color page. (Large preview)

If you click on the language icon on any page, you can see which languages that information has been translated into, and you can add your own translations following the information on the page Translating MDN Pages.

Interactive Examples

The Interactive Examples on MDN, are the examples that you will see at the top of many pages of MDN, such as this one for the grid-area property.


Screenshot of an Interactive Example


The Interactive Example for the grid-area property. (Large preview)

These examples allow visitors to MDN to try out various values for CSS properties or try out a JavaScript function, right there on MDN without needing to head into a development environment to do so. The project to add these examples has been in progress for around a year, you can read about the project and progress to date in the post Bringing Interactive Examples to MDN.

The content for these Interactive Examples is held in the Interactive Examples GitHub repository. For example, if you wanted to locate the example for grid-area, you would find it in that repo under live-examples/css-examples/grid. Under that folder, you will find two files for grid-area, an HTML and a CSS file.

grid-area.html


<section id="example-choice-list" class="example-choice-list large" data-property="grid-area">
    <div class="example-choice" initial-choice="true">
        <pre><code class="language-css">grid-area: a;</code></pre>
        <button type="button" class="copy hidden" aria-hidden="true">
        <span class="visually-hidden">Copy to Clipboard</span>
        </button>
    </div>
    
    <div class="example-choice">
        <pre><code class="language-css">grid-area: b;</code></pre>
        <button type="button" class="copy hidden" aria-hidden="true">
        <span class="visually-hidden">Copy to Clipboard</span>
        </button>
    </div>
    
    <div class="example-choice">
        <pre><code class="language-css">grid-area: c;</code></pre>
        <button type="button" class="copy hidden" aria-hidden="true">
        <span class="visually-hidden">Copy to Clipboard</span>
        </button>
    </div> 
    
    <div class="example-choice">
        <pre><code class="language-css">grid-area: 2 / 1 / 2 / 4;</code></pre>
        <button type="button" class="copy hidden" aria-hidden="true">
        <span class="visually-hidden">Copy to Clipboard</span>
        </button>
    </div> 
</section>
    
<div id="output" class="output large hidden">
    <section id="default-example" class="default-example">
        <div class="example-container">
            <div id="example-element" class="transition-all">Example</div>
        </div>
    </section>
</div>

grid.area.css


.example-container 
    background-color: #eee;
    border: .75em solid;
    padding: .75em;
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    grid-template-rows: repeat(3, minmax(40px, auto));
    grid-template-areas: 
    "a a a"
    "b c c"
    "b c c";
    grid-gap: 10px;
    width: 200px;
    
    
    .example-container > div 
    background-color: rgba(0, 0, 255, 0.2);
    border: 3px solid blue;
    
    
    example-element 
    background-color: rgba(255, 0, 200, 0.2);
    border: 3px solid rebeccapurple;
    

An Interactive Example is just a small demo, which uses some standard classes and IDs in order that the framework can pick up the example and make it interactive, where the values can be changed by a visitor to the page who wants to quickly see how it works. To add or edit an Interactive Example, first fork the Interactive Examples repo, clone it to your machine and follow the instructions on the Contributing page to install the required packages from npm and be able to build and test examples locally.

Then create a branch and edit or create your new example. Once you are happy with it, send a Pull Request to the Interactive Examples repo to ask for your example to be reviewed. In order to keep the examples consistent, reviews are fairly nitpicky but should point out the changes you need to make in a clear way, so you can update your example and have it approved, merged and added to an MDN page.


Screenshot of a tweet asking for help with HTML examples


MDN looking for help with HTML Interactive Examples. (Large preview)

With pretty much all of CSS now covered (in addition to the JavaScript examples), MDN is now looking for help to build the HTML examples. There are instructions as to how to get started in a post on the MDN Discourse Forum. Check out that post as it gives links to a Google doc that you can use to indicate that you are working on a particular example, as well as some other useful information.

The Interactive Examples are incredibly useful for people exploring the web platform, so adding to the project is an excellent way to contribute. Contributing to CSS or HTML examples requires knowledge of CSS and HTML, plus the ability to think up a clear demonstration. This last point is often the hardest part, I’ve created a lot of CSS Interactive Examples and spent more time thinking up the best example for each property than I do actually writing the code.

Browser Compat Data

Fairly recently the browser compatibility data listed on MDN Pages has begun to be updated through the Browser Compatibility Project. This project is developing browser compat data in JSON format, which can display the compatibility tables on MDN but also be useful data for other purposes.


An example screenshot of the old tables on MDN


The Old Browser Compat Tables on MDN. (Large preview)


An example screenshot of the new tables on MDN


The New Browser Compat Tables on MDN. (Large preview)

The Browser Compatibility Data is on GitHub, and if you find a page that has incorrect information or is still using the old tables, you can submit a Pull Request. The repository contains contribution information, however, the simplest way to start is to edit an existing example. I recently updated the information for the CSS shape-outside property. The property already had some data in the new format, but it was incomplete and incorrect.

To edit this data, I first forked the Browser Compat Data so that I had my own fork. I then cloned that to my machine and created a new branch to make my changes in.

Once I had my new branch, I found the JSON file for shape-outside and was able to make my edits. I already had a good idea about browser support for the property; I also used the live example on the shape-outside MDN page to test to see support when I wasn’t sure. Therefore making the edits was a case of working through the file, checking the version numbers listed for support of the property and updating those which were incorrect.

As the file is in JSON format is pretty straightforward to edit in any text editor. The .editorconfig file explains the simple formatting rules for these documents. There are also some helpful tips in this checklist.

Once you have made your edits, you can commit your changes, push your branch to your fork and then make a Pull Request to the Browser Compat Data repository. It’s likely that, as with the live examples, the reviewer will have some changes for you to make. In my PR for the Shapes data I had a few errors in how I had flagged the data and needed to make some changes to links. These were simple to make, and then my PR was merged.

Get Started

You can get started simply by picking something to add to and starting work on it in many cases. If you have any questions or need some help with any of this, then the MDN Discourse forum is a good place to post. MDN is the place I go to look up information, the place I send new developers and experienced developers alike, and its strength is the fact that we can all work to make it better.

If you have never made a Pull Request on a project before, it is a very friendly place to make that first PR and, as I hope I have shown, there are ways to contribute that don’t require writing any code at all. A very valuable skill for any documentation project is that of writing, editing and translating as these skills can help to make technical documentation easier to read and accessible to more people around the world.

Smashing Editorial
(il)


Read this article:

Contributing To MDN Web Docs

Designing For Accessibility And Inclusion




Designing For Accessibility And Inclusion

Steven Lambert



“Accessibility is solved at the design stage.” This is a phrase that Daniel Na and his team heard over and over again while attending a conference. To design for accessibility means to be inclusive to the needs of your users. This includes your target users, users outside of your target demographic, users with disabilities, and even users from different cultures and countries. Understanding those needs is the key to crafting better and more accessible experiences for them.

One of the most common problems when designing for accessibility is knowing what needs you should design for. It’s not that we intentionally design to exclude users, it’s just that “we don’t know what we don’t know.” So, when it comes to accessibility, there’s a lot to know.

How do we go about understanding the myriad of users and their needs? How can we ensure that their needs are met in our design? To answer these questions, I have found that it is helpful to apply a critical analysis technique of viewing a design through different lenses.

“Good [accessible] design happens when you view your [design] from many different perspectives, or lenses.”

The Art of Game Design: A Book of Lenses

A lens is “a narrowed filter through which a topic can be considered or examined.” Often used to examine works of art, literature, or film, lenses ask us to leave behind our worldview and instead view the world through a different context.

For example, viewing art through a lens of history asks us to understand the “social, political, economic, cultural, and/or intellectual climate of the time.” This allows us to better understand what world influences affected the artist and how that shaped the artwork and its message.

Accessibility lenses are a filter that we can use to understand how different aspects of the design affect the needs of the users. Each lens presents a set of questions to ask yourself throughout the design process. By using these lenses, you will become more inclusive to the needs of your users, allowing you to design a more accessible user experience for all.

The Lenses of Accessibility are:

You should know that not every lens will apply to every design. While some can apply to every design, others are more situational. What works best in one design may not work for another.

The questions provided by each lens are merely a tool to help you understand what problems may arise. As always, you should test your design with users to ensure it’s usable and accessible to them.

Lens Of Animation And Effects

Effective animations can help bring a page and brand to life, guide the users focus, and help orient a user. But animations are a double-edged sword. Not only can misusing animations cause confusion or be distracting, but they can also be potentially deadly for some users.

Fast flashing effects (defined as flashing more than three times a second) or high-intensity effects and patterns can cause seizures, known as ‘photosensitive epilepsy.’ Photosensitivity can also cause headaches, nausea, and dizziness. Users with photosensitive epilepsy have to be very careful when using the web as they never know when something might cause a seizure.

Other effects, such as parallax or motion effects, can cause some users to feel dizzy or experience vertigo due to vestibular sensitivity. The vestibular system controls a person’s balance and sense of motion. When this system doesn’t function as it should, it causes dizziness and nausea.

“Imagine a world where your internal gyroscope is not working properly. Very similar to being intoxicated, things seem to move of their own accord, your feet never quite seem to be stable underneath you, and your senses are moving faster or slower than your body.”

A Primer To Vestibular Disorders

Constant animations or motion can also be distracting to users, especially to users who have difficulty concentrating. GIFs are notably problematic as our eyes are drawn towards movement, making it easy to be distracted by anything that updates or moves constantly.

This isn’t to say that animation is bad and you shouldn’t use it. Instead you should understand why you’re using the animation and how to design safer animations. Generally speaking, you should try to design animations that cover small distances, match direction and speed of other moving objects (including scroll), and are relatively small to the screen size.

You should also provide controls or options to cater the experience for the user. For example, Slack lets you hide animated images or emojis as both a global setting and on a per image basis.

To use the Lens of Animation and Effects, ask yourself these questions:

  • Are there any effects that could cause a seizure?
  • Are there any animations or effects that could cause dizziness or vertigo through use of motion?
  • Are there any animations that could be distracting by constantly moving, blinking, or auto-updating?
  • Is it possible to provide controls or options to stop, pause, hide, or change the frequency of any animations or effects?

Lens Of Audio And Video

Autoplaying videos and audio can be pretty annoying. Not only do they break a users concentration, but they also force the user to hunt down the offending media and mute or stop it. As a general rule, don’t autoplay media.

“Use autoplay sparingly. Autoplay can be a powerful engagement tool, but it can also annoy users if undesired sound is played or they perceive unnecessary resource usage (e.g. data, battery) as the result of unwanted video playback.”

Google Autoplay guidelines

You’re now probably asking, “But what if I autoplay the video in the background but keep it muted?” While using videos as backgrounds may be a growing trend in today’s web design, background videos suffer from the same problems as GIFs and constant moving animations: they can be distracting. As such, you should provide controls or options to pause or disable the video.

Along with controls, videos should have transcripts and/or subtitles so users can consume the content in a way that works best for them. Users who are visually impaired or who would rather read instead of watch the video need a transcript, while users who aren’t able to or don’t want to listen to the video need subtitles.

To use the Lens of Audio and Video, ask yourself these questions:

  • Are there any audio or video that could be annoying by autoplaying?
  • Is it possible to provide controls to stop, pause, or hide any audio or videos that autoplay?
  • Do videos have transcripts and/or subtitles?

Lens Of Color

Color plays an important part in a design. Colors evoke emotions, feelings, and ideas. Colors can also help strengthen a brand’s message and perception. Yet the power of colors is lost when a user can’t see them or perceives them differently.

Color blindness affects roughly 1 in 12 men and 1 in 200 women. Deuteranopia (red-green color blindness) is the most common form of color blindness, affecting about 6% of men. Users with red-green color blindness typically perceive reds, greens, and oranges as yellowish.


Color Blindness Reference Chart for Deuternaopia, Protanopia, and Tritanopia


Deuteranopia (green color blindness) is common and causes reds to appear brown/yellow and greens to appear beige. Protanopia (red color blindness) is rare and causes reds to appear dark/black and orange/greens to appear yellow. Tritanopia (blue-yellow colorblindness) is very rare and cases blues to appear more green/teal and yellows to appear violet/grey. (Source) (Large preview)

Color meaning is also problematic for international users. Colors mean different things in different countries and cultures. In Western cultures, red is typically used to represent negative trends and green positive trends, but the opposite is true in Eastern and Asian cultures.

Because colors and their meanings can be lost either through cultural differences or color blindness, you should always add a non-color identifier. Identifiers such as icons or text descriptions can help bridge cultural differences while patterns work well to distinguish between colors.


Six colored labels. Five use a pattern while the sixth doesn’t


Trello’s color blind friendly labels use different patterns to distinguish between the colors. (Large preview)

Oversaturated colors, high contrasting colors, and even just the color yellow can be uncomfortable and unsettling for some users, prominently those on the autism spectrum. It’s best to avoid high concentrations of these types of colors to help users remain comfortable.

Poor contrast between foreground and background colors make it harder to see for users with low vision, using a low-end monitor, or who are just in direct sunlight. All text, icons, and any focus indicators used for users using a keyboard should meet a minimum contrast ratio of 4.5:1 to the background color.

You should also ensure your design and colors work well in different settings of Windows High Contrast mode. A common pitfall is that text becomes invisible on certain high contrast mode backgrounds.

To use the Lens of Color, ask yourself these questions:

  • If the color was removed from the design, what meaning would be lost?
  • How could I provide meaning without using color?
  • Are any colors oversaturated or have high contrast that could cause users to become overstimulated or uncomfortable?
  • Does the foreground and background color of all text, icons, and focus indicators meet contrast ratio guidelines of 4.5:1?

Lens Of Controls

Controls, also called ‘interactive content,’ are any UI elements that the user can interact with, be they buttons, links, inputs, or any HTML element with an event listener. Controls that are too small or too close together can cause lots of problems for users.

Small controls are hard to click on for users who are unable to be accurate with a pointer, such as those with tremors, or those who suffer from reduced dexterity due to age. The default size of checkboxes and radio buttons, for example, can pose problems for older users. Even when a label is provided that could be clicked on instead, not all users know they can do so.

Controls that are too close together can cause problems for touch screen users. Fingers are big and difficult to be precise with. Accidentally touching the wrong control can cause frustration, especially if that control navigates you away or makes you lose your context.


Tweet that says Software being Done is like lawn being Mowed. Jim Benson


When touching a single line tweet, it’s very easy to accidentally click the person’s name or handle instead of opening the tweet because there’s not enough space between them. (Source) (Large preview)

Controls that are nested inside another control can also contribute to touch errors. Not only is it not allowed in the HTML spec, it also makes it easy to accidentally select the parent control instead of the one you wanted.

To give users enough room to accurately select a control, the recommended minimum size for a control is 34 by 34 device independent pixels, but Google recommends at least 48 by 48 pixels, while the WCAG spec recommends at least 44 by 44 pixels. This size also includes any padding the control has. So a control could visually be 24 by 24 pixels but with an additional 10 pixels of padding on all sides would bring it up to 44 by 44 pixels.

It’s also recommended that controls be placed far enough apart to reduce touch errors. Microsoft recommends at least 8 pixels of spacing while Google recommends controls be spaced at least 32 pixels apart.

Controls should also have a visible text label. Not only do screen readers require the text label to know what the control does, but it’s been shown that text labels help all users better understand a controls purpose. This is especially important for form inputs and icons.

To use the Lens of Controls, ask yourself these questions:

  • Are any controls not large enough for someone to touch?
  • Are any controls too close together that would make it easy to touch the wrong one?
  • Are there any controls inside another control or clickable region?
  • Do all controls have a visible text label?

Lens Of Font

In the early days of the web, we designed web pages with a font size between 9 and 14 pixels. This worked out just fine back then as monitors had a relatively known screen size. We designed thinking that the browser window was a constant, something that couldn’t be changed.

Technology today is very different than it was 20 years ago. Today, browsers can be used on any device of any size, from a small watch to a huge 4K screen. We can no longer use fixed font sizes to design our sites. Font sizes must be as responsive as the design itself.

Not only should the font sizes be responsive, but the design should be flexible enough to allow users to customize the font size, line height, or letter spacing to a comfortable reading level. Many users make use of custom CSS that helps them have a better reading experience.

The font itself should be easy to read. You may be wondering if one font is more readable than another. The truth of the matter is that the font doesn’t really make a difference to readability. Instead it’s the font style that plays an important role in a fonts readability.

Decorative or cursive font styles are harder to read for many users, but especially problematic for users with dyslexia. Small font sizes, italicized text, and all uppercase text are also difficult for users. Overall, larger text, shorter line lengths, taller line heights, and increased letter spacing can help all users have a better reading experience.

To use the Lens of Font, ask yourself these questions:

  • Is the design flexible enough that the font could be modified to a comfortable reading level by the user?
  • Is the font style easy to read?

Lens Of Images and Icons

They say, “A picture is worth a thousand words.” Still, a picture you can’t see is speechless, right?

Images can be used in a design to convey a specific meaning or feeling. Other times they can be used to simplify complex ideas. Whichever the case for the image, a user who uses a screen reader needs to be told what the meaning of the image is.

As the designer, you understand best the meaning or information the image conveys. As such, you should annotate the design with this information so it’s not left out or misinterpreted later. This will be used to create the alt text for the image.

How you describe an image depends entirely on context, or how much textual information is already available that describes the information. It also depends on if the image is just for decoration, conveys meaning, or contains text.

“You almost never describe what the picture looks like, instead you explain the information the picture contains.”

Five Golden Rules for Compliant Alt Text

Since knowing how to describe an image can be difficult, there’s a handy decision tree to help when deciding. Generally speaking, if the image is decorational or there’s surrounding text that already describes the image’s information, no further information is needed. Otherwise you should describe the information of the image. If the image contains text, repeat the text in the description as well.

Descriptions should be succinct. It’s recommended to use no more than two sentences, but aim for one concise sentence when possible. This allows users to quickly understand the image without having to listen to a lengthy description.

As an example, if you were to describe this image for a screen reader, what would you say?


Vincent van Gogh’s The Starry Night


Source (Large preview)

Since we describe the information of the image and not the image itself, the description could be Vincent van Gogh’s The Starry Night since there is no other surrounding context that describes it. What you shouldn’t put is a description of the style of the painting or what the picture looks like.

If the information of the image would require a lengthy description, such as a complex chart, you shouldn’t put that description in the alt text. Instead, you should still use a short description for the alt text and then provide the long description as either a caption or link to a different page.

This way, users can still get the most important information quickly but have the ability to dig in further if they wish. If the image is of a chart, you should repeat the data of the chart just like you would for text in the image.

If the platform you are designing for allows users to upload images, you should provide a way for the user to enter the alt text along with the image. For example, Twitter allows its users to write alt text when they upload an image to a tweet.

To use the Lens of Images and Icons, ask yourself these questions:

  • Does any image contain information that would be lost if it was not viewable?
  • How could I provide the information in a non-visual way?
  • If the image is controlled by the user, is it possible to provide a way for them to enter the alt text description?

Lens Of Keyboard

Keyboard accessibility is among the most important aspects of an accessible design, yet it is also among the most overlooked.

There are many reasons why a user would use a keyboard instead of a mouse. Users who use a screen reader use the keyboard to read the page. A user with tremors may use a keyboard because it provides better accuracy than a mouse. Even power users will use a keyboard because it’s faster and more efficient.

A user using a keyboard typically uses the tab key to navigate to each control in sequence. A logical order for the tab order greatly helps users know where the next key press will take them. In western cultures, this usually means from left to right, top to bottom. Unexpected tab orders results in users becoming lost and having to scan frantically for where the focus went.

Sequential tab order also means that they must tab through all controls that are before the one that they want. If that control is tens or hundreds of keystrokes away, it can be a real pain point for the user.

By making the most important user flows nearer to the top of the tab order, we can help enable our users to be more efficient and effective. However, this isn’t always possible nor practical to do. In these cases, providing a way to quickly jump to a particular flow or content can still allow them to be efficient. This is why “skip to content” links are helpful.

A good example of this is Facebook which provides a keyboard navigation menu that allows users to jump to specific sections of the site. This greatly speeds up the ability for a user to interact with the page and the content they want.


facebook


Facebook provides a way for all keyboard users to jump to specific sections of the page, or other pages within Facebook, as well as an Accessibility Help menu. (Large preview)

When tabbing through a design, focus styles should always be visible or a user can easily become lost. Just like an unexpected tab order, not having good focus indicators results in users not knowing what is currently focused and having to scan the page.

Changing the look of the default focus indicator can sometimes improve the experience for users. A good focus indicator doesn’t rely on color alone to indicate focus (Lens of Color), and should be distinct enough to easily allow the user to find it. For example, a blue focus ring around a similarly colored blue button may not be visually distinct to discern that it is focused.

Although this lens focuses on keyboard accessibility, it’s important to note that it applies to any way a user could interact with a website without a mouse. Devices such as mouth sticks, switch access buttons, sip and puff buttons, and eye tracking software all require the page to be keyboard accessible.

By improving keyboard accessibility, you allow a wide range of users better access to your site.

To use the Lens of Keyboard, ask yourself these questions:

  • What keyboard navigation order makes the most sense for the design?
  • How could a keyboard user get to what they want in the quickest way possible?
  • Is the focus indicator always visible and visually distinct?

Lens Of Layout

Layout contributes a great deal to the usability of a site. Having a layout that is easy to follow with easy to find content makes all the difference to your users. A layout should have a meaningful and logical sequence for the user.

With the advent of CSS Grid, being able to change the layout to be more meaningful based on the available space is easier than ever. However, changing the visual layout creates problems for users who rely on the structural layout of the page.

The structural layout is what is used by screen readers and users using a keyboard. When the visual layout changes but not the underlying structural layout, these users can become confused as their tab order is no longer logical. If you must change the visual layout, you should do so by changing the structural layout so users using a keyboard maintain a sequential and logical tab order.

The layout should be resizable and flexible to a minimum of 320 pixels with no horizontal scroll bars so that it can be viewed comfortably on a phone. The layout should also be flexible enough to be zoomed in to 400% (also with no horizontal scroll bars) for users who need to increase the font size for a better reading experience.

Users using a screen magnifier benefit when related content is in close proximity to one another. A screen magnifier only provides the user with a small view of the entire layout, so content that is related but far away, or changes far away from where the interaction occurred is hard to find and can go unnoticed.

GIF of CodePen showing that clicking on a button does not update the interface
When performing a search on CodePen, the search button is in the top right corner of the page. Clicking the button reveals a large search input on the opposite side of the screen. A user using a screen magnifier would be hard pressed to notice the change and would think the button doesn’t work. (Large preview)

To use the Lens of Layout, ask yourself these questions:

  • Does the layout have a meaningful and logical sequence?
  • What should happen to the layout when it’s viewed on a small screen or zoomed in to 400%?
  • Is content that is related or changes due to user interaction in close proximity to one another?

Lens Of Material Honesty

Material honesty is an architectural design value that states that a material should be honest to itself and not be used as a substitute for another material. It means that concrete should look like concrete and not be painted or sculpted to look like bricks.

Material honesty values and celebrates the unique properties and characteristics of each material. An architect who follows material honesty knows when each material should be used and how to use it without tarnishing itself.

Material honesty is not a hard and fast rule though. It lies on a continuum. Like all values, you are allowed to break them when you understand them. As the saying goes, they are “more what you’d call “guidelines” than actual rules.”

When applied to web design, material honesty means that one element or component shouldn’t look, behave, or function as if it were another element or component. Doing so would cheat the user and could lead to confusion. A common example of this are buttons that look like links or links that look like buttons.

Links and buttons have different behaviors and affordances. A link is activated with the enter key, typically takes you to a different page, and has a special context menu on right click. Buttons are activated with the space key, used primarily to trigger interactions on the current page, and have no such context menu.

When a link is styled to look like a button or vise versa, a user could become confused as it does not behave and function as it looks. If the “button” navigates the user away unexpectedly, they might become frustrated if they lost data in the process.

“At first glance everything looks fine, but it won’t stand up to scrutiny. As soon as such a website is stress‐tested by actual usage across a range of browsers, the façade crumbles.”

Resilient Web Design

Where this becomes the most problematic is when a link and button are styled the same and are placed next to one another. As there is nothing to differentiate between the two, a user can accidentally navigate when they thought they wouldn’t.


Three links and/or buttons shown inline with text


Can you tell which one of these will navigate you away from the page and which won’t? (Large preview)

When a component behaves differently than expected, it can easily lead to problems for users using a keyboard or screen reader. An autocomplete menu that is more than an autocomplete menu is one such example.

Autocomplete is used to suggest or predict the rest of a word a user is typing. An autocomplete menu allows a user to select from a large list of options when not all options can be shown.

An autocomplete menu is typically attached to an input field and is navigated with the up and down arrow keys, keeping the focus inside the input field. When a user selects an option from the list, that option will override the text in the input field. Autocomplete menus are meant to be lists of just text.

The problem arises when an autocomplete menu starts to gain more behaviors. Not only can you select an option from the list, but you can edit it, delete it, or even expand or collapse sections. The autocomplete menu is no longer just a simple list of selectable text.




With the addition of edit, delete, and profile buttons, this autocomplete menu is materially dishonest. (Large preview)

The added behaviors no longer mean you can just use the up and down arrows to select an option. Each option now has more than one action, so a user needs to be able to traverse two dimensions instead of just one. This means that a user using a keyboard could become confused on how to operate the component.

Screen readers suffer the most from this change of behavior as there is no easy way to help them understand it. A lot of work will be required to ensure the menu is accessible to a screen reader by using non-standard means. As such, it will might result in a sub-par or inaccessible experience for them.

To avoid these issues, it’s best to be honest to the user and the design. Instead of combining two distinct behaviors (an autocomplete menu and edit and delete functionality), leave them as two separate behaviors. Use an autocomplete menu to just autocomplete the name of a user, and have a different component or page to edit and delete users.

To use the Lens of Material Honesty, ask yourself these questions:

  • Is the design being honest to the user?
  • Are there any elements that behave, look, or function as another element?
  • Are there any components that combine distinct behaviors into a single component? Does doing so make the component materially dishonest?

Lens Of Readability

Have you ever picked up a book only to get a few paragraphs or pages in and want to give up because the text was too hard to read? Hard to read content is mentally taxing and tiring.

Sentence length, paragraph length, and complexity of language all contribute to how readable the text is. Complex language can pose problems for users, especially those with cognitive disabilities or who aren’t fluent in the language.

Along with using plain and simple language, you should ensure each paragraph focuses on a single idea. A paragraph with a single idea is easier to remember and digest. The same is true of a sentence with fewer words.

Another contributor to the readability of content is the length of a line. The ideal line length is often quoted to be between 45 and 75 characters. A line that is too long causes users to lose focus and makes it harder to move to the next line correctly, while a line that is too short causes users to jump too often, causing fatigue on the eyes.

“The subconscious mind is energized when jumping to the next line. At the beginning of every new line the reader is focused, but this focus gradually wears off over the duration of the line”

— Typographie: A Manual of Design

You should also break up the content with headings, lists, or images to give mental breaks to the reader and support different learning styles. Use headings to logically group and summarize the information. Headings, links, controls, and labels should be clear and descriptive to enhance the users ability to comprehend.

To use the Lens of Readability, ask yourself these questions:

  • Is the language plain and simple?
  • Does each paragraph focus on a single idea?
  • Are there any long paragraphs or long blocks of unbroken text?
  • Are all headings, links, controls, and labels clear and descriptive?

Lens Of Structure

As mentioned in the Lens of Layout, the structural layout is what is used by screen readers and users using a keyboard. While the Lens of Layout focused on the visual layout, the Lens of Structure focuses on the structural layout, or the underlying HTML and semantics of the design.

As a designer, you may not write the structural layout of your designs. This shouldn’t stop you from thinking about how your design will ultimately be structured though. Otherwise, your design may result in an inaccessible experience for a screen reader.

Take for example a design for a single elimination tournament bracket.


Eight person tournament bracket featuring George, Fred, Linus, Lucy, Jack, Jill, Fred, and Ginger. Ginger ultimately wins against George.


Large preview

How would you know if this design was accessible to a user using a screen reader? Without understanding structure and semantics, you may not. As it stands, the design would probably result in an inaccessible experience for a user using a screen reader.

To understand why that is, we first must understand that a screen reader reads a page and its content in sequential order. This means that every name in the first column of the tournament would be read, followed by all the names in the second column, then third, then the last.

“George, Fred, Linus, Lucy, Jack, Jill, Fred, Ginger, George, Lucy, Jack, Ginger, George, Ginger, Ginger.”

If all you had was a list of seemingly random names, how would you interpret the results of the tournament? Could you say who won the tournament? Or who won game 6?

With nothing more to work with, a user using a screen reader would probably be a bit confused about the results. To be able to understand the visual design, we must provide the user with more information in the structural design.

This means that as a designer you need to know how a screen reader interacts with the HTML elements on a page so you know how to enhance their experience.

  • Landmark Elements (header, nav, main, and footer)
    Allow a screen reader to jump to important sections in the design.
  • Headings (h1h6)
    Allow a screen reader to scan the page and get a high level overview. Screen readers can also jump to any heading.
  • Lists (ul and ol)
    Group related items together, and allow a screen reader to easily jump from one item to another.
  • Buttons
    Trigger interactions on the current page.
  • Links
    Navigate or retrieve information.
  • Form labels
    Tell screen readers what each form input is.

Knowing this, how might we provide more meaning to a user using a screen reader?

To start, we could group each column of the tournament into rounds and use headings to label each round. This way, a screen reader would understand when a new round takes place.

Next, we could help the user understand which players are playing against each other each game. We can again use headings to label each game, allowing them to find any game they might be interested in.

By just adding headings, the content would read as follows:

“__Round 1, Game 1__, George, Fred, __Game 2__, Linus, Lucy, __Game 3__, Jack, Jill, __Game 4__, Fred, Ginger, __Round 2, Game 5__, George, Lucy, __Game 6__, Jack, Ginger, __Round 3__, __Game 7__, George, Ginger, __Winner__, Ginger.”

This is already a lot more understandable than before.

The information still doesn’t answer who won a game though. To know that, you’d have to understand which game a winner plays next to see who won the previous game. For example, you’d have to know that the winner of game four plays in game six to know who advanced from game four.

We can further enhance the experience by informing the user who won each game so they don’t have to go hunting for it. Putting the text “(winner)” after the person who won the round would suffice.

We should also further group the games and rounds together using lists. Lists provide the structural semantics of the design, essentially informing the user of the connected nodes from the visual design.

If we translate this back into a visual design, the result could look as follows:


The tournament bracket


The tournament with descriptive headings and winner information (shown here with grey background). (Large preview)

Since the headings and winner text are redundant in the visual design, you could hide them just from visual users so the end visual result looks just like the first design.

“If the end result is visually the same as where we started, why did we go through all this?” You may ask.

The reason is that you should always annotate your design with all the necessary structural design requirements needed for a better screen reader experience. This way, the person who implements the design knows to add them. If you had just handed the first design to the implementer, it would more than likely end up inaccessible.

To use the Lens of Structure, ask yourself these questions:

  • Can I outline a rough HTML structure of my design?
  • How can I structure the design to better help a screen reader understand the content or find the content they want?
  • How can I help the person who will implement the design understand the intended structure?

Lens Of Time

Periodically in a design you may need to limit the amount of time a user can spend on a task. Sometimes it may be for security reasons, such as a session timeout. Other times it could be due to a non-functional requirement, such as a time constrained test.

Whatever the reason, you should understand that some users may need more time in order finish the task. Some users might need more time to understand the content, others might not be able to perform the task quickly, and a lot of the time they could just have been interrupted.

“The designer should assume that people will be interrupted during their activities”

— The Design of Everyday Things

Users who need more time to perform an action should be able to adjust or remove a time limit when possible. For example, with a session timeout you could alert the user when their session is about to expire and allow them to extend it.

To use the Lens of Time, ask yourself this question:

  • Is it possible to provide controls to adjust or remove time limits?

Bringing It All Together

So now that you’ve learned about the different lenses of accessibility through which you can view your design, what do you do with them?

The lenses can be used at any point in the design process, even after the design has been shipped to your users. Just start with a few of them at hand, and one at a time carefully analyze the design through a lens.

Ask yourself the questions and see if anything should be adjusted to better meet the needs of a user. As you slowly make changes, bring in other lenses and repeat the process.

By looking through your design one lens at a time, you’ll be able to refine the experience to better meet users’ needs. As you are more inclusive to the needs of your users, you will create a more accessible design for all your users.

Using lenses and insightful questions to examine principles of accessibility was heavily influenced by Jesse Schell and his book “The Art of Game Design: A Book of Lenses.”

Smashing Editorial
(il, ra, yk)


Taken from – 

Designing For Accessibility And Inclusion

The Current State Of Email Marketing Programming: What Can And Can’t Be Used

Many people want to create the best email campaigns possible, and this goal can be realized by following best practices for email design and coding and by implementing advanced techniques correctly. This comprehensive guide, for novices and pros alike, delves deep into the nitty gritty of email marketing.

Here’s what you’ll learn:

  • best practices for email design, from creating a theme to designing the footer;
  • how to add images and incorporate rich media (GIFs, cinemagraphs, video) in your emails;
  • how to design responsive emails for a better user experience;
  • email client support for responsive mobile emails;
  • finally, advanced techniques in email design.

Introduction

Emails have transformed from being an ordinary text-based personal communication tool into a future-proof marketing channel. We have moved into a world of visually attractive HTML emails that have the feel of microsites in the inbox.

Getting acquainted with the best practices of email coding is, therefore, imperative if you want to avoid a broken user experience and instead improve user engagement. Moreover, as the digital world becomes more mobile, creating responsive emails is the need of the hour.

In this article, we shall delve deeper into best practices to follow for all email clients, as well as advanced techniques you can include for email clients that support interactive elements.

Let’s start with the basic structure of an email.

Basic Email Structure

As Leonardo da Vinci said, ”Simplicity is the ultimate sophistication.” Accordingly, keep the design of your email simple.

Check out the email design below by Charity: Water. Simple yet engaging.

A simple yet engaging email design by Charity: Water.


View large version

Developers have been coding emails using <table> layouts for a long time now. So, it is recommended that you place your email elements in a grid-based layout, rather than arbitrarily placed. Moreover, any element that might overlap needs to be added to a different layer.

The email shown above by Charity: Water looks like this when exported to a tabular layout:

Email design by Charity: Water divided into a grid.


View large version

Email design is made up of different subelements. Let’s explore them now.

1. Email Theme

The logo is not the only element that reflects your brand’s personality. The overall theme of your email, including the fonts, color scheme and imagery, should be in sync with branding guidelines.

2. Width And Height Of Email Template

Because your subscribers use diverse email clients and devices, your email should be appropriately visible in the preview pane of all email clients. Keep in mind that the email will be displayed according to the display pane of the email service provider or client. Only certain email clients, such as Thunderbird, Apple Mail and native mobile email clients, will display email at full width.

For other email clients, the display boxes have variable sizes. Many service providers, such as MailChimp, go over the basics of HTML email, by recommending, for example, 600 to 800 pixels as a width, so that the full email gets displayed. Remember, that most subscribers never use the horizontal scroll bar in an email.

The height of your email template should usually be long enough to accommodate your copy within two scroll lengths. You can certainly have a longer email template if you have to convey a huge amount of information. However, if your email template gets too long, it might become boring for subscribers, who will be less likely to scroll to the end to check out all of the offers and promotions included.

The height of the preview pane of most email clients (which contains content commonly referred to as “above the fold”) is generally between 300 and 500 pixels. Make the best use of this space, so that the content included above the fold entices the subscriber to scroll down.

Every email developer knows that if an email’s file size exceeds 102 KB, Gmail’s app will clip the email, and they will not be able to track metrics.

Check out the screenshot below to see what an email looks like in Gmail when it is clipped:

Email message, the weight of which exceeds 102 KB, as seen in Gmail, with ‘View entire message’ at the end.


View large version

To avoid Gmail’s clip, make sure your email does not have unnecessary code and is not over-formatted. Go for a minimalist email design, without any shortened URLs. Note that images will not be embedded in the email and, so, will not increase the file’s size. That being said, removing unnecessary images will help to reduce the email size.

For marketers who use predesigned templates, the height and width will already be taken care of. If you want to use your own design, consider the ideal width and height of an email template.

3. Body Of Email

Emails usually begin with a hero image at the top, followed by the main copy, a call to action and then the footer.

Because most people read on screens positioned about 2 to 3 feet away, your h1 title should be around 16 pixels; if your title is short, it could even go up to 20 pixels. A good idea would be to render the h1 title as text, along with an attractive hero image.

Your descriptive text should not be smaller than 12 pixels. It should be easily readable across all email clients and devices. Moreover, the alignment of paragraphs and paragraph size also play an important role.

4. Call To Action

The primary objective of email marketing is to persuade customers to take action. To do that, your call to action (CTA) should have engaging, actionable verbs. Use convincing and actionable text, like “Start the free trial,” rather than drab phrases like “Click here.”

An interesting study by ContentVerve, “10 Call-to-Action Case Studies With Takeaways and Examples From Real Button Tests”,” shows that use of the first-person perspective in CTAs increase clicks by 90%, regardless of the product. For example, “Get my free copy” converts better than “Get your free copy.”

Create a sense of urgency in CTAs and get higher click-through rates by adding the word “now.”

This email from 'Alice and Olivia' has a CTA in bright pink, contrasting with the white background.


View large version

Campaign Monitor, in one of its guides, “10 Tips to Optimize Your Calls to Action,” emphasizes that a CTA button should always contrast strongly with the background color, so that it doesn’t blend in and that it grabs the subscriber’s attention. Based on your target audience, your industry and the message to be conveyed, including CTAs at regular intervals can increase email conversions and the desired subscriber action. Its height should be at least 30 pixels, and it should be easily tappable with a thumb on mobile devices.

Check out the email below from Asana. It places a CTA strategically above the first fold and also follows the CTA best practices discussed above.

Email by Asana strategically places CTA above the first fold.
Email by Asana strategically places CTA above the first fold. (View large version)

5. Images And Interactive Elements

If you are putting images or rich media in your email, add relevant alternative (alt) text, so that the purpose of the email is preserved even when the visuals are blocked by the email client. This is also greatly helpful with accessibility, because screen readers will be able to read the alternative text and convey your message.

Most email marketers tend to send emails consisting of a single image, which is first of many common HTML mistakes compiled by MailChimp. It recommends a text-to-image ratio of 80 to 20, to make sure that emails do not get trapped in spam filters. According to a recent study by MailChimp, 200 words per image yield a good click-through rate.

Using linked images in your email ensures an optimum file size. Load images from an external server using <img> tags.

The main advantage of this technique is that you can change images even after sending the email. It makes the email light and reduces the time taken to send the email. The disadvantage is that subscribers will have to download the images from the external server, which will incur download costs for those on metered connections, and the images might also get blocked by some email services.

Rich media elements, such as GIFs, cinemagraphs and video, are becoming popular in email these days.

You can add a GIF or cinemagraph in an email simply by uploading the file to the server that stores your images. Then, copy the URL and use the following HTML:

<pre class="lang:default decode:true" title="Code for adding GIFs or Cinemagraphs in Email"><img src="/wp-content/uploads/thefiletobeinserted.gif">
</pre>

Test the email to make sure that the GIF works properly.

Embedding video is a very adaptable technique of web development, but unfortunately, it’s not supported in email. Therefore, opt for HTML5 video.

To add a video in email, use the code below:

<pre class="lang:default decode:true" title="Code for including video in email"><video width="400" height="200" controls poster="http://www.art.com/images/blog_images/Imagefiles/2017/html5_video/valentinesday.jpg"><br/><source src="http://www.videofile.com/htmlfiles/movie-14thfeb.mp4" type="video/mp4"><br/><!-- fallback 1 --><br/><a href="http://www.xyz.com" ><br/><img height="200" src=" http://www.art.com/pictures/important/Imagefiles/2017/html5_video/valentinesday.jpg " width="400" /><br/></a><br/></video><br/><br/><br/>
</pre>

HTML5 primarily supports the MP4, OGG and WebM video formats.

Pro tip: Apple supports the MP4 video format in its email clients and browsers.

Some points to remember:

  • Make sure that the server configuration you use can output the right MIME type, so that the email client identifies the correct video format when retrieving the video.

  • If you are using an Apache web server, add this entry to the .htaccess file: Add Type video/mp4.mp4 m4v.

6. Number Of Email Folds

Your email should have just two folds, as mentioned earlier. The first fold should capture your brand and include the h1 title with a relevant CTA. If your email template exceeds two scrolls, then the third scroll should cross-sell your products. The idea is to change up the content and keep subscribers hooked by providing interesting information.

The footer is the most overlooked part of any email. However, it probably has information that subscribers are looking for, such as the company address, social sharing buttons and contact details. In order for your email to be CAN-SPAM compliant, the footer should have some additional elements.

An “Unsubscribe” link should allow subscribers to opt out of your mailing list easily and will reduce spam complaints.

Your contact details should link back to your company website and should include your postal and email address.

Additionally, you can have ancillary links, such as “Forward to a friend” and “View in Browser.”

As stated in “The Best Practices of Footer Design” by Bee, the fine print of your email should have the following sections:

  • Explanation of why the recipient got this email
    Your subscribers have probably subscribed to numerous mailing lists. Subtly remind recipients of the reason they received the email, to maintain your reputation as an emailer and to minimize spam complaints.
  • Copyright
    Include the copyright mark, along with the current year and your business name.
  • Privacy policy
    Link to your privacy policy, because subscribers should know where that information is stored. This is critical for e-commerce retailers.
  • Terms of use
    If you are sending out a promotional email highlighting discount offers, share the terms of use that govern the deals.

Cramming information into the footer sounds tempting, but you should determine the most important information for your business and restrict the footer to the minimum. Stuffing it with too much information could lead readers to dismiss it entirely because they will not be able to figure out which links to click.

Check out the footer below by Cotton on Body. Although it is well organized, it could be overwhelming for the subscriber who is scanning the email.

The Cotton on Body email footer, which is too lengthy.


View large version

Have a look at the footer below by Alice and Olivia. It is simple, and it maintains a visual hierarchy according to the actions they want subscribers to take.

Alice and Olivia's email footer is concise and designed with all good practices in mind.


View large version

The footer by HSN below is clean and makes good use of padding and white space. It is not overwhelming, yet it conveys important information that readers might be looking for.

HSN's footer is clean; padding and white space are used appropriately.


View large version

Mobile Responsive Emails

Most subscribers will check email on their phone. Owing to this trend, your emails ought to be responsive. Responsive design includes several elements, such as media queries, fluid grids and fluid images, so that users can view the email as intended, regardless of screen size or device. The basics of responsive email design include the table element, easily stackable sections and full-width CTAs.

If your subscriber list consists of many mobile users, then avoid overlapping layouts. Hide non-primary sections, such as navigation and email advertisements, to cater to mobile subscribers. Mobile-specific email elements such as a navigation menu and image sliders can also be used.

Responsive email design is supported in these email clients:

  • iOS Mail app
  • Windows Phone 7.5
  • Android 4.x Email (OEM) app
  • BlackBerry Z10
  • BlackBerry OS7
  • iPhone Gmail app

The following email clients do not support responsive email:

  • Android Yahoo Mail app
  • iPhone Yahoo Mail app
  • BlackBerry OS 5
  • Windows Phone 7
  • iPhone Mailbox app
  • Windows Phone 8
  • Android Gmail app
  • Windows Mobile 6.1

Responsive design enables you to do the following:

  • change hierarchy,
  • modify navigation,
  • enlarge fonts,
  • change layout,
  • scale images,
  • add padding,
  • change or hide content.

Designing Responsive Email

To make their emails responsive, developers use a media query that is commonly referred to as @media. It is a special set of CSS styles, included in the header, that work as conditional statements or dynamic rules.

The point of media queries is to identify the screen size of the device being used and to execute various rules according to that screen size. The challenge is that media queries do not work in all email clients and might need detailed planning and testing compared to other design techniques.

Have a look at the media query below:

<pre class="lang:default decode:true" title="Structure of Media Query">@media only screen and (min-width:479px) and (max-width:701px) 
.em_main_table 
     width: 100% !important;


.em_hide 
     display: none !important;

}
</pre>

When this email is accessed on a device whose screen is between 479 and 701 pixels wide, the email’s width will be 100%, according to the width: 100% !important; attribute. The !important function forces this attribute in email clients such as Gmail, where it might be ignored.

The styles in the CSS rule block should specify the container or element type that the styles will dictate. Assign these rules in the HTML if you want them to work.

Here is the CSS:

<pre class="lang:default decode:true" title="Code for CSS"> td[class="body-header"] font-size: 18px !important; 

And here is the HTML:

<pre class="lang:default decode:true" title="Code for HTML"><td align="left" class="body-header">
</pre>

It is important that the element (td) and the class (body-header) added in the CSS and HTML match each other.

Advanced Techniques

With the advent of advanced email clients, such as Apple Mail, which is based on Webkit, email developers can even play around with keyframe animation, interactive elements such as carousels, and live feeds.

Conditional coding for different email clients (such as for Outlook and for Samsung and Apple devices) has also become possible.

Conditional coding for Outlook and for Samsung and Apple devices


View large version

Wrapping Up

If you follow these simple tips, you will surely be able to create awesome email marketing campaigns that convert, whether you are a novice or pro at email programming. In the end, aim to create a good user experience and make subscribers look forward to your emails. Happy emailing!

Smashing Editorial
(da, ra, yk, al, il)

More:  

The Current State Of Email Marketing Programming: What Can And Can’t Be Used