[syndicated profile] paciellogroup_feed

Posted by Graeme Coleman

VoiceOver users interact with the web and native applications on their iOS device using a number of gestures. The simplest gesture involves swiping the screen from left to right by using a finger to navigate through page content. While there are many other gestures to support speedy navigation, a useful rule of thumb is for developers to try to reduce the number of swipes required on a page (without missing out on necessary content). In theory, this should improve the experience for those people who use VoiceOver.

Reducing the number of required swipes is particularly helpful when supporting form navigation. In HTML, assuming a developer has applied the for attribute to the label element, and its value matches the id attribute of the related input, only the input will fall into VoiceOver swipe focus order, and VoiceOver will read out the label text – for example, “First name, text field”. Unfortunately, there is no concept of providing matching for and id attributes when developing native iOS applications, hence I sometimes encounter cases where navigating through forms, and particularly large forms, can be a bewildering process.

To illustrate, let’s take an example. Imagine you have a form that contains three simple text fields:

  • Name
  • Nationality
  • Age

For each of the above three components, you may decide to drop these onto the storyboard in Xcode as follows: a Label to represent the visible label, and a Text Field to represent the related input, as in the following screenshot:

A screenshot from the storyboard in Xcode showing labels and visually associated form fields representing Name, Nationality and Age

Unfortunately, many beginners’ guides to Xcode development I encounter stop there. While it is visually obvious how the labels and associated text fields match up, this isn’t so obvious to VoiceOver users. For example, if I run the above example on an iOS device, the label is announced first. When I swipe to the related text field, VoiceOver simply announces “text field”. The problem with this approach is twofold:

  • If I navigate forwards through the form (i.e. swiping from left to right), it is reasonably obvious to identify how the text fields relate to their associated labels; that is, the label is announced by VoiceOver, followed by the text field – which is announced as “text field”. However, if I decide to swipe backwards through the form (because, say, I have forgotten to fill in a field), or I am using explore-by-touch (holding the tip of the finger on the page and moving it around until I locate the content I require), “text field” on its own does not clearly indicate which label the text field relates to. Consequently, I may enter the wrong data into the wrong text field.
  • Both the label and the text field fall into VoiceOver swipe focus order as separate elements. This means that, in the above example, a VoiceOver user must swipe six times (once for each component) in order to reach a Submit button.

To deal with the above issues, here are my recommendations.

Make sure that all form controls are labelled programmatically

The first step is to ensure that you provide an accessible label for each of the text fields. You can do this in one of two ways:

  • Provide a label for the text field in the Identity Inspector. Make sure the text matches up exactly with the visible label. Or:
  • Provide a label for the text field at code level, by applying the accessibilityLabel property to each text field. Again, make sure this text matches up exactly with the visible label.

A screenshot from the Identity Inspector in Xcode showing the text Nationality added to the Label field

The rest of this post assumes the second approach is taken, but either method is acceptable.

Example code for labelling form fields (note: for illustrative purposes only)

@IBOutlet weak var nameTextField: UITextField!
@IBOutlet weak var nationalityTextField: UITextField!
@IBOutlet weak var ageTextField: UITextField!

class ViewController: UIViewController {
…
	override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
	
	self.nameTextField.accessibilityLabel = "Name";
	self.nationalityTextField.accessibilityLabel = "Nationality";
	self.ageTextField.accessibilityLabel = "Age";
		
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
…
}

Now, whenever any of the text fields receive focus, the label will be announced. For example, VoiceOver will announce “Nationality, text field” when the Nationality text field receives focus.

Hide visible text labels from VoiceOver users

However, the above technique only partially resolves the issue. If a VoiceOver user swipes down from the top of the page, they will hear the visible label, and then by swiping right they will hear the label text again as part of the text field. This obviously results in duplication.

To resolve this issue, apply the isAccessibilityElement method to each of the visible labels, and set each to a value of false. This removes each of the visible text labels from VoiceOver swipe focus order. Consequently, only the text fields themselves are focusable, which reduces the number of swipes required through the form from six down to three.

Example code for removing visible text labels from VoiceOver swipe focus order (note: for illustrative purposes only)

@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var nationalityLabel: UILabel!
@IBOutlet weak var ageLabel: UILabel!

@IBOutlet weak var nameTextField: UITextField!
@IBOutlet weak var nationalityTextField: UITextField!
@IBOutlet weak var ageTextField: UITextField!

class ViewController: UIViewController {
…
	override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
	
	self.nameTextField.accessibilityLabel = "Name";
	self.nationalityTextField.accessibilityLabel = "Nationality";
	self.ageTextField.accessibilityLabel = "Age";
	
	self.nameLabel.isAccessibilityElement = false;
	self.nationalityLabel.isAccessibilityElement = false;
	self.ageLabel.isAccessibilityElement = false;
		
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
…
}

Be  aware that the above is a very simple example, but it highlights how strategic use of the accessibilityLabel and isAccessibilityElement properties can both ensure components are labelled correctly, and can help to reduce the number of swipes per page.

[syndicated profile] hacks_mozilla_feed

Posted by Stephanie Hobson

Kuma, the code that produces the MDN site, is a weird mix of the old and the new. MDN turned ten in 2015 and there’s still code and content around from those very first days. When I sat down to start coding the current redesign, the first thing I did was remove the last few traces of the last redesign. In contrast, we have a cutting-edge audience: 92% of our users have a browser with CSS grid support! We enabled http2, and 98% of our users have seen benefits from that.

One of the ways we deal with old code in kuma is with the campsite rule: Always leave your campsite better than you found it. A redesign touches a lot of files, and this was a great opportunity to clean up and refactor — at least until the deadline started getting close.

A redesign is also a great time to change stuff you’re afraid of breaking. People are more understanding of you working the bugs out of something new than breaking something that’s worked for years. I removed 640 lines of stale code during the redesign. (And if I broke a six-year-old XPCOM tutorial you use daily by removing the custom list-style-type, please file a bug!)

One website with two looks

Rather than working on the CSS for the redesign in a separate “redesign” folder, we duplicated all the files and added “-old” to the file name of the old files, which means that all of our redesign work is happening in the “official” files. This preserves the git history and means we don’t have to move anything around after launch. Once we’re happy with the code, we can delete the “-old” files with confidence.

To serve the new styles to our beta testers and the “-old” ones to everyone else, we use Django Waffle. Waffle can also be used to serve different content but because there’s a strong separation of presentation and content on MDN, we’ve made very few changes to the HTML.

Bugs our beta testers found

MDN is huge, and we can’t test every page in every locale. We’re really lucky to have active beta testers. :) Some of the biggest things they turned up for us were:

Highlighting

Problems with Zilla Highlight in Vietnamese and when there's inline code examples.

We started out by replicating Mozilla’s brand “highlight” effect by using the Zilla Slab Highlight font, but we abandoned that pretty quickly when problems turned up in many of our locales and when used in combination with inline code.

The current approach puts a full-width black background on h3 and h4 headings by default, and then some JavaScript runs to add a <span> tag so that the black background hugs the heading text. Progressive enhancement at work.

We went back and forth about this for a while, wondering if the JavaScript and extra <span> was worth the effort. But we stuck with it because it makes the h3 and h4 headings much easier to spot when scanning the page.

What’s Taiwanese for Slab Serif?

Showing the difference between Zilla's thick strokes and the thin strokes of Taiwanese.

Previously we used Open Sans as our heading text. With the redesign, we switched to Zilla Slab. Open Sans was thin and an average height for a font. It didn’t look out of place next to the system fallbacks for Chinese or Japanese characters.

Zilla is big and thick, and we started getting feedback about the contrast with these system fallbacks. Additionally, the character set for Zilla is European Latin only at the moment, so Vietnamese, which uses Latin characters plus a couple Latin characters not used in Europe, displayed font fallbacks in the middles of words.

To address both these problems, we implemented a system that allowed us to override the site fonts on a per-locale basis. (Comment if you’d like a separate blog post about this).

Contrast

We received many complaints about the old design’s low-contrast display. We went a bit too far the other way with this design and received complaints about the high contrast. We’ve toned it down to the ever-popular #333 now.

What’s next

We’re moving on from this to make specific improvements to the article pages:

  • Putting code samples high on the page; our hard-working writers and volunteers are doing this, one page at a time.
  • A better approach to readable line-lengths and wide code examples, inspired by the Hacks Blog theme.
  • Compatibility tables that display desktop and mobile data side by side.
  • Code samples you can experiment with in the page.

See this early by signing up to be a beta tester.

Enjoyed beta testing MDN? You can also beta-test Firefox by downloading Nightly.

Who is “we”?

The MDN dev team is:

  • Stephanie Hobson, me, CSS-Pre-Pre-Processor
  • Schalk Neethling, who reviewed each of my 30+ pull requests in ALL THE BROWSERS, sometimes multiple times
  • John Whitlock, who did the awesome locale fallbacks
  • Ryan Johnson, who always asks “Why not?” when John and I say things can’t be done.

We blog sporadically on the Mozilla Marketing Engineering & Operations blog.

You should also read this blog post by our Product Manager, Kadir Topal, about The Future of MDN.

One Illustration, Three SVG outputs

Jul. 25th, 2017 01:16 pm
[syndicated profile] csstricks_feed

Posted by Geoff Graham

Let's say we draw the same vector graphic in different design applications and export each one as SVG for use on the web. Should we expect the same SVG file from each application?

On the one hand, we might expect each file to be the same because of our past history with exporting images. Applications have typically been consistent at saving JPGs, PNGs, and GIFs with perhaps minor differences to the overall file size.

On the other hand, SVG is different than our typical image file and our expectations might need to adapt to those differences. The output of SVG might be visual, but what we're really talking about is math and code. That means an SVG file is a little more comparable to a CSS file that has been compiled from a preprocessor. Your results may vary based on the method used to compile the code.

I decided to draw the same illustration in Illustrator, Sketch, and Figma and compare exported SVG code. This post will summarize those results.

About the Illustration

It's nothing fancy. A basic plus sign with a white fill on top of a circle with a black fill. The idea was to use something that's close to an icon that would be common on any site.

The illustration was drawn three times, once in each application. Making the icon in one application then copying and pasting it in another didn't seem like a fair comparison. This allowed each application to interpret the SVG from its own native tools. I'm not the most skilled illustrator, so I made the illustration once, then traced it in the other applications to ensure everything was to scale and that all the points were nearly identical.

About the Comparison

It's worth noting that this post is not at all concerned about the "best" export of the group. What's more interesting is (1) whether there are differences in how SVG code is compiled and (2) how those possible difference might affect a front-end workflow or even influence which application is better suited for a particular project.

Here's what is being compared:

  • File Size
  • Code Structure
  • Naming Standards

One more thing with mentioning is that we're assuming default export options in this comparison. Illustrator has a robust set of options that can completely change how an SVG file is saved, where the others do not. I decided to use the default Illustrator export settings, with the minor exception of not minifying the code on export.

All good? Let's look at the results.

Side by Side Code Comparison

See the Pen One Illustration, Three SVG Outputs by Geoff Graham (@geoffgraham) on CodePen.

Table Comparison

Comparison Illustrator Sketch Figma
Export Settings Yes No No
File Size 701 Bytes 946 Bytes 1 KB
XML Header No Yes No
Includes <height> and <width> attributes No Yes Yes
Includes viewBox Attribute Yes Yes Yes
SVG ID Yes No No
SVG ID Name Generated NA NA
SVG Data Name Attribute Layer Name NA NA
Title Tag (<title>) File Name Artboard Name Layer Name
Description Tag (<description>) NA Created with Sketch Created with Figma
Includes Definitions (<defs>) No Yes Yes
Includes Groups (<g>) Yes Yes Yes
Group ID Name NA Organized by Page Name, Artboard, Group, then Layer Organized by Frame, Group, then Layer
Includes Use (<use>) No No Yes

Comparison Summary

Those are some pretty interesting results. Like I mentioned earlier, the goal here is not to declare a winner of who does things best but to gauge whether there are differences — and there certainly are differences!

File Size

One huge benefit of SVG, in general, is its small file size versus raster images. That benefit shines in all three cases. For example, the same icon exported as a PNG in Sketch came out to 12KB. Sketch's SVG output is 97% savings from its PNG counterpart.

I'm not particularly sure that the differences in file sizes between the three results here are all that crucial, despite the fact that Illustrator's output results in a file size that is ~30% smaller than Figma's output. I only say that because it's likely that the SVG file that gets used in production gets minified and cached in the same fashion that makes it all very negligible.

That said, the fact that there is a file size difference at all might influence which build tools you use for your SVG workflow and how the settings for that build tool are configured.

Code Structure

The difference in file size really comes down to how each application structures the code it compiles. For example, where Figma is super into grouping and defining shapes and paths for the sake of making them more reusable in different contexts, Illustrator avoids them altogether and tends to make the file easier to drop inline.

Again, the goal is not to determine whether one approach is better than the other, but recognize that there are different philosophies going into the generated file and let that help determine the right tool for the current job. You might get a smaller file size in one instance, but perhaps more flexibility in another, depending on your needs and priorities.

Naming Standards

Another case in point is how Illustrator uses unique generated IDs on the <svg> element by default. That makes dropping the file inline much less likely to conflict with other inline files where a designer may have used the same file, artboard or layer names across multiple files. By contrast, neither Sketch nor Figma uses an ID directly on the SVG element.

There are build tools that will help craft ID and class names but, if you are tasked with editing an SVG file manually or have to use a file as it's provided to you for some reason, then knowing how an application names things might influence how you approach your work.

Wrapping Up

The biggest takeaway for me from this comparison is a reminder that SVG is code at the end of the day. The applications we use to illustration vector graphics are simply a GUI for creating code and the way that code gets written is likely to be different based on who is writing it.

It's really no different than something like the CodePen Rodeo (when is the next one, by the way?) where a single design is provided and many people go off to code it in their own ways. There is no "right" way to code it, but it's fun to see how different people take different paths to achieve the same deliverable.

The bottom line underscored by this comparison is that we can't take the assets we have for granted. As much as we may enjoy the fact that machines are willing to make decisions on our behalf, a front-end workflow is still overwhelmingly a subjective task and influences how we do our jobs.


One Illustration, Three SVG outputs is a post from CSS-Tricks

[syndicated profile] paciellogroup_feed

Posted by Matthew Atkinson

This is an opinion piece, looking at one slice of accessibility, to highlight some trends and possibilities. All of the computing devices, platforms and assistive technologies discussed within empower people (the author included) and are a vital part of the progress that has been and is being made.

The ideal, and the current reality

In the physical world, we may need glasses, magnifiers, telescopes, to help us perceive physical things, but in the electronic world, the content—and even the interface to that content—can, and should, adapt to us. My ideal electronic system is one in which information is presented in a way that I can access “just like that”—without the need to look through the limiting lens of a screen magnifier (as empowering as such lenses are these days).

Panning and scrolling are the necessary evils of screen-magnification. The physical and cognitive load of being zoomed in to a small area of the overall screen, constantly panning about to find content of interest can present bigger barriers than you might think. It can be tiring, and is easy to get lost, or miss important content because it’s in an unexpected area of the overall screen.


Representation of full-screen magnification. The user is zoomed into a specific area of the overall screen. They must pan around the “real” screen to find content and interface controls to operate.

The challenges

In recent years, some challenges to progress towards our ideal of adaptation have cropped up.

Layout on the Web becomes rigid

Web pages aren’t like physical documents: they don’t have to become huge and unwieldy when enlarged like photocopied paper: the content within a web page can be “re-flowed”, scrolling vertically if it became too big to fit on-screen at once. That’s how it (usually) worked in the olden days: web content was enlarged by increasing the base font size, and scrolled vertically—nice and manageable, even when using screen-magnification (in which case people could either pan across each line to read it, or opt to keep the content narrow, to fit within their zoom area, and just scroll a bit more, keeping navigation simple).

However, as layout on the web became more sophisticated, and perhaps because of user expectations from physical documents, the desire to preserve that layout when the page is zoomed took hold, and “full-page” (2D) zoom became the default, whereas “text-only” (vertical-scrolling) zoom became an increasingly hard-to-find option, within the ever-leaner browser UIs.

This put screen-magnification users in the peculiar and perplexing world of parallax scrolling, where the screen, and the web content, must be panned independently, each in two different directions. It is at this point that most people would feel that both limbs and brain cells are in short supply, and that there must be a better way.

Representation of trying to access “full-page” (2D) zoomed web content whilst also using full-screen magnification. The user has to pan around the web content, which is within a window that, in turn, is within the “real” screen, which the user also has to pan around. This creates two levels of 2D scrolling, which is hard, and tiring, to navigate successfully.

So many pixels!

High-resolution screens (sometimes termed “retina” displays) provide clearer, more vivid rendering of text and images, though unfortunately for those with low vision, they also have tended to cause the subtitles and credits on TV shows, and the menus on computer screens, to appear even more tiny than before.

The all-new mobile paradigm… isn’t, quite

Modern smartphones and smartwatches provide new ways to interact and can be wonderfully empowering, especially when it comes to navigating the world around independently (with maps apps, and apps to say which platform your train is on, and the like). They have helped content and app authors come up with new ways to bring people the information they need, in simpler ways, often depending on where (and when) they are. This shift to a new way of doing things offered a lot of potential to bring assistive technologies into the mainstream, and do things differently, in pursuit of the goal of adaptivity.

However, even the smallest-screened devices fall back on the traditional “magnifier” approach to help people with vision impairment. If zooming into a large desktop monitor is frustrating, then having to zoom and pan around a small ‘phone screen really makes one feel boxed in.

Further, many people find some small on-screen text hard to read, and many people might benefit from in-built features such as magnifiers in ‘phones, but such features are often labelled as “accessibility” features, which most people don’t really understand, or identify as being helpful to them.

Some opportunities

The above challenges, however, have presented some opportunities for improving accessibility—in some cases to all users; not just people with vision impairments.

Layout becomes responsive

One consequence of the way in which modern browsers zoom layout is that, whilst the content gets bigger, the “viewport” (the conceptual available space for the content) is also getting smaller—when the content is enlarged, the viewport can accommodate less content.

This is actually a familiar situation: ‘phones and small tablets are the everyday small-screen devices, and the techniques that enable web-content to adapt to differing viewport sizes can be used to improve desktop accessibility. In fact, with mobile-first design, the “also happens to be accessible” mobile design can be seen as taking precedence, and only adapting to larger viewports available on some tablet and desktop devices if need be.

Crisper zoomed content

One benefit to such high resolutions being available to all is that scaling features in operating systems have necessarily had to not only continue to be supported, but made easier and simpler to access. Further, whilst it may not benefit all people with vision-impairments, interfaces and content that have been zoomed on a high-resolution display will benefit from those added pixels, and do appear clearer than they would on earlier low-resolution displays.

Global minimum font size—starting steps

It’s not just about content (web or otherwise); users need to be able to perceive a user interface in order to be able to interact with it. Most operating systems provide a usually-optional means for apps to support large text. iOS has the “Dynamic Type” API that app developers must explicitly support; Android offers the ability to specify an interface in flexible units that adapt to both the size of the display and the user’s preferred base font size or zoom factor (though only a small range is presently permitted, so that apps still fit on the screen).

These developments are welcome, but they can only go so far: the layout of an app might change a little from ‘phone to tablet, but it is still fundamentally fixed, as all variations have to be anticipated and designed by the developer in advance, so it cannot adapt to users who need even larger fonts, or perhaps people with dexterity difficulties who require large touch targets, or both at the same time. Surely there must be a better way?

The potential—for all

There is a better way! The world of academic research has a lot to offer in terms of innovative approaches to adaptation that can improve accessibility for people with various impairments—either due to disability or situation—and even multiple impairments at the same time. In future articles, we will look at some of these adaptations.

[syndicated profile] hacks_mozilla_feed

Posted by Charles Siebert

A-Frame makes building 3D and VR web applications easy, so developers of all skill levels can create rich and interactive virtual worlds – and help make the web the best and largest deployment surface for VR content. For an Oregon State University capstone project focused on WebVR, our team investigated performance and optimizations for A-Frame on Android smartphones. We developed a means of benchmarking the level of 3D complexity a mobile phone is capable of, and determining which performance metrics are required for such a benchmark.

Team OVRAR!

From the left, Team OVRAR (Optimizing Virtual Reality and Augmented Reality):

Branden Berlin: Javascript Compatibility and Model Lighting
Charles Siebert: Team Captain, Project Designer, and Modeling
Yipeng (Roger) Song: Animations and Texturing

Results and Recommendations

Texture size: The framework resizes textures to the nearest power of two, which heavily increases the loading and rendering workload in the scenes. We found that high-resolution textures that didn’t match the criteria reached sizes of 8196×8196, with one texture taking up to 20 MB! Using texture dimensions that are a power of two helps ensure optimal memory use. Check the Web Console for warnings when textures are resized.

Asset Limit: We found that having more than 70 MB of assets loaded for one web page was unrealistic in a phone environment. It caused significant delays in loading the scene fully, and in some cases crashed the browser on our phones. Use the Allocations recorder in the Performance Tool in Firefox to check your scene’s memory usage, and the A-Frame Inspector to tune aspects of rendering for individual objects.

Tree map

Resolution cost: Higher resolution trees caused delays in loading the models and significant slowdowns in rendering the scenes. Our high resolution tree features 37,000 vertices which increases the graphics rendering workload, including lighting from multiple light sources. This heavily limited the number of models we could load into our scene. We also found an upper limit for our devices while handling these trees: When our room reached about 1,000,000 vertices, our phone browsers would crash after spending a few minutes attempting to load and render. You can add the “stats” property to your tag to see the number of vertices in the scene.

Object count: Load times increased linearly based on the number of models to be drawn to the scene. This would add a significant amount of time, if each object to be loaded took, for example, three milliseconds. Further inspecting the memory snapshot shows that our object models are read in and stored into object arrays for quicker access and rendering. Larger object models would also increase linearly based off the number of vertices and faces that are used to create the model, and their resulting normal vectors. Check the A-Frame stats monitor to keep an eye on your object count.

Measurement overhead: During the testing, we used WebIDE to monitor on-device performance. We found that the overhead of USB debugging on our Android devices caused performance to drop by nearly half. Our testing showed that CPU performance was not the leading bottleneck in rendering the scenes. CPU usage hovered at 10-25% during heavy performance drops. This shows that the rendering is mostly done on the GPU, which follows how OpenGL ES 2.0 operates in this framework.

Testing Approach

Our approach was to:

  • render multiple scenes while measuring specific metrics
  • determine the best practices for those metrics on mobile
  • report any relevant bugs that appear.

The purpose of creating a benchmark application for a mobile device is to give a baseline for what is possible to develop, so developers can use this information to plan their own projects.

We tested on the LG Nexus 5X and used the WebIDE feature in Firefox Nightly to pull performance statistics from the phone while it was rendering our scenes, tracking frames-per-second (FPS), and using memory. Additionally, we tracked processor usage on the device through Android’s native developer settings.

To begin, we broke down the fundamental parts of what goes into rendering computer graphics, and created separate scenes to test each of these parts on the device. We tested object modeling, texturing, animation, and lighting, and then created standards of performance that the phone needed to meet for each. We aimed to first find a baseline performance of 30 FPS for each part and then find the upper bound – the point at which the feature breaks or causes visual drops in performance. We separated these features by creating a VR environment with four “rooms” that tested each in A-Frame.

Room 1: Loading object models using obj-loader

Room 4 screenshot

In the first room, we implemented a high-resolution tree, loading a large number of low vertice-count objects and comparing to a low number of high vertice-count objects. Having a comparable number of vertices rendered in either scene helped us determine the performance impact of loading multiple objects at once.

Room 2: Animations and textures

In this room, we implemented textures and animations to determine the impact on initial load times and the impact in calculating animation methods. We used A-Frame’s built-in functions to attach assets to objects to texture them, and we used A-Frame’s animation methods to animate the objects in this room. This allowed us to easily test this scenario of animating the textured objects and measure the differences between the two iterations. In the first iteration, we implemented low-resolution textures on objects to compare them with high-resolution textures in the second iteration. These resolution sizes varied from 256×256 to 8196×8196. We also wanted to compare the performance between the two rooms, and see if texturing the objects would cause any unforeseen issues with animations other than the initial load time when downloading the assets from the web page.

Room 3: User interaction and lighting

This room’s initial concept focused on the basis of gaming: user interaction. We utilized JavaScript within A-Frame to allow the user to interact with objects scattered about a field. Due to the limited mobility of mobile-VR interaction, we kept it to visual interaction. Once the user looked at an object, it would either shrink or enlarge. We wanted to see if any geometric change due to interaction would impact hardware demand. We manipulated the growth size of object interactions and found a few unreliable stutters. Generally, though, the hardware performance was stable.

For the second iteration, we ramped up the effects of user interactions. We saw that nothing changed when it came to physical effects on objects in the world, so we decided to include something that is more taxing on the hardware: lighting.

As the user interacted with an object, the object would then turn into a light source, producing an ambient light at maximum intensity. We scattered these objects around the room and had the user turn them on, one by one. We started with 10 ‘suns’ and noticed an initial lag when loading the room, as well as a 2-3 second FPS drop to 13, when turning on the first sphere. After that, the rest of the spheres turned on smoothly. We noticed a steady and consistent drop of about 10 FPS for every 10 max-intensity light sources. However, as the intensity was decreased, more and more lighting sources were allowed before a noticeable change in performance occurred.

Room 3 screenshots

Room 4: All previous features implemented together.

Developers are unlikely to use just one of these specific features when creating their applications. We created this room to determine if the performance would drop at an exponential rate if all features were added together, as this would be a realistic scenario.

Further Information

You can find all the source code and documentation for our OVRAR project on Github.

If you have any questions, ask in the comments below. Thanks!

[syndicated profile] csstricks_feed

Posted by Sarah Drasner

A bit of a wordy title, huh? What is server side rendering? What does it have to do with routing and page transitions? What the heck is Nuxt.js? Funnily enough, even though it sounds complex, working with Nuxt.js and exploring the benefits of isn't too difficult. Let's get started!

Server side rendering

You might have heard people talking about server side rendering as of late. We looked at one method to do that with React recently. One particularly compelling aspect is the performance benefits. When we render our HTML, CSS, and JavaScript on the server, we often have less JavaScript to parse both initially and on subsequent updates. This article does really well going into more depth on the subject. My favorite takeaway is:

By rendering on the server, you can cache the final shape of your data.

Instead of grabbing JSON or other information from the server, parsing it, then using JavaScript to create layouts of that information, we're doing a lot of those calculations upfront, and only sending down the actual HTML, CSS, and JavaScript that we need. This can reap a lot of benefits with caching, SEO, and speed up our apps and sites.

What is Nuxt.js?

Server side rendering sounds pretty nice, but you're probably wondering if it's difficult to set up. I've been using Nuxt.js for my Vue applications lately and found it surprisingly simple to work with. To be clear: you don't need to use Nuxt.js in particular to do server side rendering. I'm just a fan of this tool for many reasons. I ran some tests last month and found that Nuxt.js had even higher lighthouse scores out of the gate than Vue's PWA template, which I thought was impressive.

Nuxt.js is a higher-level framework that you can use with a CLI command that you can use to create universal Vue applications. Here are some, not all, of the benefits:

  • Server-Side Rendering
  • Automatic Code Splitting
  • Powerful Routing System
  • Great lighthouse scores out of the gate 🐎
  • Static File Serving
  • ES6/ES7 Transpilation
  • Hot reloading in Development
  • Pre-processors: SASS, LESS, Stylus, etc
  • Write Vue Files to create your pages and layouts!
  • My personal favorite: easily add transitions to your pages

Let's set up a basic application with some routing to see the benefits for ourselves.

Getting Set up

The first thing we need to do if you haven't already is download Vue's CLI. You can do so globally with this command:

npm install -g vue-cli

# ... or ...
 
yarn add global vue-cli

You will only need to do this once, not every time you use it.

Next, we'll use the CLI to scaffold a new project, but we'll use Nuxt.js as the template:

vue init nuxt/starter my-project
cd my-project
yarn  # or...  npm install
npm run dev

You'll see the progress of the app being built and it will give you a dedicated development server to check out: http://127.0.0.1:3000/. This is what you'll see right away (with a pretty cool little animation):

Screenshot of Nuxt starting screen

Let's take a look at what's creating this initial view of our application at this point. We can go to the `pages` directory, and inside see that we have an `index.vue` page. If we open that up, we'll see all of the markup that it took to create that page. We'll also see that it's a `.vue` file, using single file components just like any ordinary `vue` file, with a template tag for the HTML, a script tag for our scripts, where we're importing a component, and some styles in a style tag. (If you aren't familiar with these, there's more info on what those are here.) The coolest part of this whole thing is that this `.vue` file doesn't require any special setup. It's placed in the `pages` directory, and Nuxt.js will automatically make this server-side rendered page!

Let's create a new page and set up some routing between them. In `pages/index.vue`, dump the content that's already there, and replace it with:

<template>
  <div class="container">
    <h1>Welcome!</h1>
    <p><nuxt-link to="/product">Product page</nuxt-link></p>
  </div>
</template>

<style>
.container {
  font-family: "Quicksand", "Source Sans Pro", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; /* 1 */
  padding: 60px;
}
</style>

Then let's create another page in the pages directory, we'll call it `product.vue` and put this content inside of it:

<template>
  <div class="container">
    <h1>This is the product page</h1>
    <p><nuxt-link to="/">Home page</nuxt-link></p>
  </div>
</template>

Right away, you'll see this:

Ta-da! 🏆
Right away, we have server side rendering, routing between pages (if you check out the URL you can see it's going between the index page and product page), and we even have a sweet little green loader that zips across the top. We didn't have to do much at all to get that going.

You might have noticed in here, there's a special little element: <nuxt-link to="/">. This tag can be used like an a tag, where it wraps around a bit of content, and it will set up an internal routing link between our pages. We'll use to="/page-title-here" instead of an href.

Now, let's add some transitions. We’ll do this in a few stages: simple to complex.

Creating Page Transitions

We already have a really cool progress bar that runs across the top of the screen as we’re routing and makes the whole thing feel very zippy. (That’s a technical term). While I like it very much, it won’t really fit the direction we’re headed in, so let’s get rid of it for now.

We're going to go into our `nuxt.config.js` file and change the lines:

/*
** Customize the progress-bar color
*/
loading: { color: '#3B8070' },

to

loading: false,

You'll also notice a few other things in this nuxt.config.js file. You'll see our meta and head tags as well as the content that will be rendered inside of them. That's because we won't have a traditional `index.html` file as we do in our normal CLI build, Nuxt.js is going to parse and build our `index.vue` file together with these tags and then render the content for us, on the server. If you need to add CSS files, fonts, or the like, we would use this Nuxt.js config file to do so.

Now that we have all that down, let's understand what's available to us to create page transitions. In order to understand what’s happening on the page that we’re plugging into, we need to review how the transition component in Vue works. I've written an article all about this here, so if you'd like deeper knowledge on the subject, you can check that out. But what you really need to know is this: under the hood, Nuxt.js will plug into the functionality of Vue's transition component, and gives us some defaults and hooks to work with:

transition component hooks

You can see here that we have a hook for what we want to happen right before the animation starts enter, during the animation/transition enter-active, and when it finishes. We have these same hooks for when something is leaving, prepended with leave instead. We can make simple transitions that just interpolate between states, or we could plug a full CSS or JavaScript animation into them.

Usually in a Vue application, we would wrap a component or element in <transition> in order to use this slick little functionality, but Nuxt.js will provide this for us at the get-go. Our hook for the page will begin with, thankfully- page. All we have to do to create an animation between pages is add a bit of CSS that plugs into the hooks:

.page-enter-active, .page-leave-active {
  transition: all .25s ease-out;
}
.page-enter, .page-leave-active {
  opacity: 0;
  transform-origin: 50% 50%;
}

I'm also going to add an extra bit of styling here so that you can see the page transitions a little easier:

html, body {
  font-family: "Quicksand", "Source Sans Pro", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; /* 1 */
  background: #222;
  color: white;
  width: 100vw;
  height: 100vh;
}

a, a:visited {
  color: #3edada;
  text-decoration: none;
}

.container {
  padding: 60px;
  width: 100vw;
  height: 100vh;
  background: #444;
}

Right now we're using a CSS Transition. This only gives us the ability to designate what to do in the middle of two states. We could do something a little more interesting by having an animation adjust in a way that suggests where something is coming from and going to. For that to happen, we could separate out transitions for page-enter and page-leave-active classes, but it's a little more DRY to use a CSS animation and specify where things are coming from and going to, and plug into each for .page-enter-active, and .page-leave-active:

.page-enter-active {
  animation: acrossIn .45s ease-out both;
} 

.page-leave-active {
  animation: acrossOut .65s ease-in both;
} 

@keyframes acrossIn {
  0% {
    transform: translate3d(-100%, 0, 0);
  }
  100% {
    transform: translate3d(0, 0, 0);
  }
}

@keyframes acrossOut {
  0% {
    transform: translate3d(0, 0, 0);
  }
  100% {
    transform: translate3d(100%, 0, 0);
  }
}

Let's also add a little bit of special styling to the product page so we can see the difference between these two pages:

<style scoped>
  .container {
    background: #222;
  }
</style>

This scoped tag is pretty cool because it will apply the styles for this page/vue file only. If you have heard of CSS Modules, you'll be familiar with this concept.

We would see this (this page is for demo purposes only, that's probably too much movement for a typical page transition):

Now, let's say we have a page with a totally different interaction. For this page, the movement up and down was too much, we just want a simple fade. For this case, we'd need to rename our transition hook to separate it out.

Let’s create another page, we’ll call it the contact page and create it in the pages directory.

<template>
  <div class="container">
    <h1>This is the contact page</h1>
    <p><nuxt-link to="/">Home page</nuxt-link></p>
  </div>
</template>

<script>
export default {
  transition: 'fadeOpacity'
}
</script>

<style>
.fadeOpacity-enter-active, .fadeOpacity-leave-active {
  transition: opacity .35s ease-out;
}

.fadeOpacity-enter, .fadeOpacity-leave-active {
  opacity: 0;
}
</style>

Now we can have two-page transitions:

You can see how we could build on these further and create more and more streamlined CSS animations per page. But from here let's dive into my favorite, JavaScript animations, and create page transitions with a bit more horsepower.

Javascript Hooks

Vue's <transition> component offers some hooks to use JavaScript animation in place of CSS as well. They are as follows, and each hook is optional. The :css="false" binding lets Vue know we're going to use JS for this animation:

<transition 
  @before-enter="beforeEnter"
  @enter="enter"
  @after-enter="afterEnter"
  @enter-cancelled="enterCancelled"

  @before-Leave="beforeLeave"
  @leave="leave"
  @after-leave="afterLeave"
  @leave-cancelled="leaveCancelled"
  :css="false">
 
 </transition>

The other thing we have available to us are transition modes. I'm a big fan of these, as you can state that one animation will wait for the other animation to finish transitioning out before transitioning in. The transition mode we will work with will be called out-in.

We can do something really wild with JavaScript and the transition mode, again, we're going a little nuts here for the purposes of demo, we would usually do something much more subtle:

In order to do something like this, I've run yarn add gsap because I'm using GreenSock for this animation. In my `index.vue` page, I can remove the existing CSS animation and add this into the <script> tags:

import { TweenMax, Back } from 'gsap'

export default {
  transition: {
    mode: 'out-in',
    css: false,
    beforeEnter (el) {
      TweenMax.set(el, {
        transformPerspective: 600,
        perspective: 300,
        transformStyle: 'preserve-3d'
      })
    },
    enter (el, done) {
      TweenMax.to(el, 1, {
        rotationY: 360,
        transformOrigin: '50% 50%',
        ease: Back.easeOut
      })
      done()
    },
    leave (el, done) {
      TweenMax.to(el, 1, {
        rotationY: 0,
        transformOrigin: '50% 50%',
        ease: Back.easeIn
      })
      done()
    }
  }
}

All of the code for these demos exist in my Intro to Vue repo for starter materials if you're getting ramped up learning Vue.

One thing I want to call out here is that currently there is a bug for transition modes in Nuxt.js. This bug is fixed, but the release hasn't come out yet. It should be all fixed and up to date in the upcoming 1.0 release, but in the meantime, here is a working simple sample demo, and the issue to track.

With this working code and those JavaScript hooks we can start to get much fancier and create unique effects, with different transitions on every page:

Here's the site that the demo was deployed to if you'd like to see it live: https://nuxt-type.now.sh/ as well as the repo that houses the code for it: https://github.com/sdras/nuxt-type

Navigation

In that last demo you might have noticed we had a common navigation across all of the pages what we routed. In order to create this, we can go into the `layouts` directory, and we'll see a file called `default.vue`. This directory will house the base layouts for all of our pages, "default" being the, uhm, default :)

Right away you'll see this:

<template>
  <div>
    <nuxt/>
  </div>
</template>

That special <nuxt/> tag will be where our `.vue` pages files will be inserted, so in order to create a navigation, we could insert a navigation component like this:

<template>
  <div>
    <img class="moon" src="~assets/FullMoon2010.png" />
    <Navigation />
    <nuxt/>
  </div>
</template>

<script>
import Navigation from '~components/Navigation.vue'

export default {
  components: {
    Navigation
  }
}
</script>

I love this because everything is kept nice and organized between our global and local needs.

I then have a component called Navigation in a directory I've called `components` (this is pretty standard fare for a Vue app). In this file, you'll see a bunch of links to the different pages:

<nav>
  <div class="title">
    <nuxt-link to="/rufina">Rufina</nuxt-link>
    <nuxt-link to="/prata">Prata</nuxt-link>
    <nuxt-link exact to="/">Playfair</nuxt-link>
  </div>
</nav>

You'll notice I'm using that <nuxt-link> tag again even though it's in another directory, and the routing will still work. But that last page has one extra attribute, the exact attribute: <nuxt-link exact to="/">Playfair</nuxt-link> This is because there are many routes that match just the `/` directory, all of them do, in fact. So if we specify exact, Nuxt will know that we only mean the index page in particular.

Further Resources

If you'd like more information about Nuxt, their documentation is pretty sweet and has a lot of examples to get you going. If you'd like to learn more about Vue, I've just made a course on Frontend Masters and all of the materials are open source here, or you can check out our Guide to Vue, or you can go to the docs which are extremely well-written. Happy coding!


Simple Server Side Rendering, Routing, and Page Transitions with Nuxt.js is a post from CSS-Tricks

Putting on a conference

Jul. 24th, 2017 12:53 pm
[syndicated profile] adactio_feed

It’s been a few weeks now since Patterns Day and I’m still buzzing from it. I might be biased, but I think it was a great success all ‘round—for attendees, for speakers, and for us at Clearleft organising the event.

I first had the idea for Patterns Day quite a while back. To turn the idea into reality meant running some numbers. Patterns Day wouldn’t have been possible without Alis. She did all the logistical work—the hard stuff—which freed me up to concentrate on the line-up. I started to think about who I could invite to speak, and at the same time, started looking for a venue.

I knew from the start that I wanted it to be one-day single-track conference in Brighton, much like Responsive Day Out. I knew I wouldn’t be able to use the Corn Exchange again—there’s extensive rebuilding going on there this year. I put together a shortlist of Brighton venues and Alis investigated their capacities and costs, but to be honest, I knew that I wanted to have it in the Duke Of York’s. I love that place, and I knew from attending FFconf that it makes for an excellent conference venue.

The seating capacity of the Duke Of York’s is quite a bit less than the Corn Exchange, so I knew the ticket price would have to be higher than that of Responsive Day Out. The Duke Of York’s isn’t cheap to rent for the day either (but worth every penny).

To calculate the ticket price, I had to figure out the overall costs:

  • Venue hire,
  • A/V hire,
  • Printing costs (for name badges, or in this case, stickers),
  • Payment provider commission—we use Stripe through the excellent Ti.to,
  • Speaker’s travel,
  • Speaker’s accommodation,
  • Speaker’s dinner the evening before the event,
  • Speaker’s payment.

Some conference organisers think they can skimp on that last part. Those conference organisers are wrong. A conference is nothing without its speakers. They are literally the reason why people buy tickets.

Because the speakers make or break a conference, there’s a real temptation to play it safe and only book people who are veterans. But then you’re missing out on a chance to boost someone when they’re just starting out with public speaking. I remember taking a chance on Alla a few years back for Responsive Day Out 3—she had never given a conference talk before. She, of course, gave a superb talk. Now she’s speaking at events all over the world, and I have to admit, it gives me a warm glow inside. When it came time for Patterns Day, Alla had migrated into the “safe bet” category—I knew she’d deliver the perfect closing keynote.

I understand why conference organisers feel like they need to play it safe. From their perspective, they’re already taking on a lot of risk in putting on a conference in the first place. It’s easy to think of yourself as being in a position of vulnerability—”If I don’t sell enough tickets, I’m screwed!” But I think it’s important to realise that you’re also in a position of power, whether you like it or not. If you’re in charge of putting together the line-up of a conference, that’s a big responsibility, not just to the attendees on the day, but to the community as a whole. It’s like that quote by Eliel Saarinen:

Always design a thing by considering it in its next larger context. A chair in a room, a room in a house, a house in an environment, an environment in a city plan.

Part of that responsibility to the wider community is representation. That’s why I fundamentally disagree with ppk when he says:

The other view would be that there should be 50% woman speakers. Although that sounds great I personally never believed in this argument. It’s based on the general population instead of the population of web developers, and if we’d extend that argument to its logical conclusion then 99.9% of the web development conference speakers should know nothing about web development, since that’s the rough ratio in the general population.

That makes it sound like a conference’s job is to represent the status quo. By that logic, the line-up should include plenty of bad speakers—after all, the majority of web developers aren’t necessarily good speakers. But of course that’s not how conferences work. They don’t represent typical ideas—quite the opposite. What’s the point of having an event that simply reinforces the general consensus? This isn’t Harrison Bergeron. You want a line-up that’s exceptional.

I don’t think conference organisers can shirk this issue and say “It’s out of my hands; I’m just reflecting the way things are.” The whole point of having a conference in the first place is to trigger some kind of change. If you’re not happy with the current make-up of the web community (and I most definitely am not), then a conference is the perfect opportunity to try to demonstrate an alternative. We do it with the subject matter of the talks—”Our code/process/tooling doesn’t have to be this way!”—and I think we should also apply that to the wider context: “Our culture doesn’t have to be this way!”

Passing up that chance isn’t just a missed opportunity, I think it’s also an abdication of responsibility. Believe me, I know that organising a conference is a lot of work, but that’s not a reason to cop out. On the contrary, it’s all the more reason to step up to the plate and try your damnedest to make a difference. Otherwise, why even have a conference?

Whenever the issue of diversity at conferences comes up, there is inevitably someone who says “All I care about is having the best speakers.” But if that were true, shouldn’t your conference (and every other conference) have exactly the same line-up every year?

The truth is that there are all sorts of factors that play into the choice of speakers. I think representation should be a factor, but that’s all it is—one factor of many. Is the subject matter relevant? That’s a factor. Do we already have someone on the line-up covering similar subject matter? That’s a factor. How much will it cost to get this speaker? That’s a factor. Is the speaker travelling from very far away? That’s a factor.

In the case of Patterns Day, I had to factor in the range of topics. I wanted a mixture of big-picture talks as well as hands-on nitty-gritty case studies. I also didn’t want it to be too developer-focused or too design-focused. I was aiming for a good mix of both.

In the end, I must admit that I am guilty of doing exactly what I’ve been railing against. I played it safe. I put together a line-up of speakers that I wanted to see, and that I knew with absolute certainty would deliver great presentations. There were plenty of potential issues for me to get stressed about in the run-up to the event, but the quality of the talks wasn’t one of them. On the one hand, I wish I had taken more chances with the line-up, but honestly, if I could do it over again, I wouldn’t change a thing.

Because I was trying to keep the ticket price as low as possible—and the venue hire was already a significant cost—I set myself the constraint of only having speakers from within the UK (Jina was the exception—she was going to come anyway as an attendee, so of course I asked her to speak). Knowing that the speaker’s travel costs would be low, I could plug the numbers into an algebraic formula for figuring out the ticket price:

costs ÷ seats = price

Add up all the costs and divide that total by the number of available seats to get the minimum ticket price.

In practice, you probably don’t want to have to sell absolutely every single ticket just to break even, so you set the price for a sales figure lower than 100%—maybe 80%, or 50% if you’re out to make a tidy profit (although if you’re out to make a tidy profit, I don’t think conferences are the right business to be in—ask any conference organiser).

Some conferences factor in money for sponsorship to make the event happen. I prefer to have sponsors literally sponsoring additions to the conference. In the case of Patterns Day, the coffee and pastries were sponsored by Deliveroo, and the videos were sponsored by Amazon. But sponsorship didn’t affect the pricing formula.

The Duke Of York’s has around 280 seats. I factored in about 30 seats for speakers, Clearlefties, and other staff. That left 250 seats available for attendees. But that’s not the number I plugged into the pricing formula. Instead, I chose to put 210 tickets on sale and figured out the ticket price accordingly.

What happened to the remaining 40 seats? The majority of them went to Codebar students and organisers. So if you bought a ticket for Patterns Day, you directly subsidised the opportunity for people under-represented in technology to attend. Thank you.

Speaking personally, I found that having the Codebar crew in attendance really made my day. They’re my heroes, and it meant the world to me that they were able to be there.

Zara, Alice, and Amber Patterns Day Anwen, Zara, Alice, Dot, and Amber Eden, Zara, Alice, and Chloe

[syndicated profile] csstricks_feed

Posted by Manuel Matuzovic

A few weeks ago I held a CSS Grid Layout workshop. Since I'm, like most of us, also pretty new to the topic, I learned a lot while preparing the slides and demos.
I decided to share some of the stuff that was particularly interesting to me, with you.

Have fun!

Negative values lower than -1 may be used for grid-row-end and grid-column-end

In a lot of code examples and tutorials you will see that you can use grid-column-start: 1 and grid-column-end: -1 (or the shorthand grid-column: 1 / -1) to span an element from the first line to the last. My friend Max made me aware that it's possible to use lower values than -1 as well.

.grid-item {
  grid-column: 1 / -2;
}

For example, you can set grid-column: 1 / -2 to span the cells between the first and the second to last line.

See the Pen Grid item from first to second to last by Manuel Matuzovic (@matuzo) on CodePen.

It's possible to use negative values in grid-column/row-start

Another interesting thing about negative values is that you can use them on grid-column/row-start as well. The difference between positive and negative values is that with negative values the placement will come from the opposite side. If you set grid-column-start: -2 the item will be placed on the second to last line.

.item {
  grid-column-start: -3;
  grid-row: -2;
}

See the Pen Negative values in grid-column/row-start by Manuel Matuzovic (@matuzo) on CodePen.

Generated content pseudo-elements (::before and ::after) are treated as grid items

It may seem obvious that pseudo-elements generated with CSS become grid items if they're within a grid container, but I wasn't sure about that. So I created a quick demo to verify it. In the following Pen you can see that generated elements become grid- and flex-items if they are within a corresponding container.

See the Pen Experiment: Pseudo elements as grid items by Manuel Matuzovic (@matuzo) on CodePen.

Animating CSS Grid Layout properties

According to the CSS Grid Layout Module Level 1 specification there are 5 animatable grid properties:

  • grid-gap, grid-row-gap, grid-column-gap
  • grid-template-columns, grid-template-rows

Currently only the animation of grid-gap, grid-row-gap, grid-column-gap is implemented and only in Firefox and Firefox Mobile. I wrote a post about animating CSS Grid Layout properties, where you'll find some more details and a demo.

The value of grid-column/row-end can be lower than the start value

In level 4 of the CSS Grid Garden game I learned that the value of grid-column-end or grid-row-end may be lower than the respective start equivalent.

.item:first-child {
  grid-column-end: 2;
  grid-column-start: 4;
}

The item in the above code will start on the 4th line and end on the 2nd, or in other words, start on the 2nd line and end on the 4th.

See the Pen Lower grid-column-end value than grid-column-start by Manuel Matuzovic (@matuzo) on CodePen.

Using the `span` keyword on grid-column/row-start and grid-column/row-end

A grid item by default spans a single cell. If you want to change that, the span keyword can be quite convenient. For example setting grid-column-start: 1 and grid-column-end: span 2 will make the grid item span two cells, from the first to the third line.

You can also use the span keyword with grid-column-start. If you set grid-column-end: -1 and grid-column-start: span 2 the grid-item will be placed at the last line and span 2 cells, from the last to third to last line.

See the Pen CSS Grid Layout: span keyword by Manuel Matuzovic (@matuzo) on CodePen.

grid-template-areas and implicit named lines

If you create template areas in a grid, you automatically get four implicit named lines, two naming the row-start and row-end and two for the column-start and column-end. By adding the -start or -end suffix to the name of the area, they're applicable like any other named line.

.grid {
  display: grid;
  grid-template-columns: 1fr 200px 200px;
  grid-template-areas: 
    "header header header"
    "articles ads posts"
}

.footer {
  grid-column-start: ads-start;
  grid-column-end: posts-end;
}

See an example for implicit named lines in this Pen.

Grid is available in the insider version of Microsoft Edge

Support for CSS Grid Layout is pretty great since all major browsers, except IE and Edge, support it. For a lot of projects you can start using CSS Grid Layouts today. Support for Microsoft Edge will probably come pretty soon, because it's already available in the insider version of Microsoft Edge.

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

Desktop

ChromeOperaFirefoxIEEdgeSafari
57445211*1610.1

Mobile / Tablet

iOS SafariOpera MobileOpera MiniAndroidAndroid ChromeAndroid Firefox
10.3NoNo565954

If you want to learn more about Grids check out The Complete Guide to Grid, Getting Started with CSS Grid, Grid By Example and my Collection of Grid demos on CodePen.


A Collection of Interesting Facts about CSS Grid Layout is a post from CSS-Tricks

The Next Generation of Web Gaming

Jul. 20th, 2017 03:21 pm
[syndicated profile] hacks_mozilla_feed

Posted by Andre Vrignaud

Over the last few years, Mozilla has worked closely with other browsers and the industry to advance the state of games on the Web. Together, we have enabled developers to deploy native code on the web, first via asm.js, and then with its successor WebAssembly. Now available in Firefox and Chrome, and also soon in Edge and WebKit, WebAssembly enables near-native performance of code in the browser, which is great for game development, and has also shown benefits for WebVR applications. WebAssembly code is able to deliver more predictable performance due to JIT compilation and garbage collection being avoided. Its wide support across all major browser engines opens up paths to near-native speed, making it possible to build high-performing plugin-free games on the web.

“In 2017 Kongregate saw a shift away from Flash with nearly 60% of new titles using HTML5,” said Emily Greer, co-founder and CEO of Kongregate.  “Developers were able to take advantage of improvements in HTML5 technologies and tools while consumers were able to enjoy games without the need for 3rd-party plugins.  As HTML5 continues to evolve it will enable developers to create even more advanced games that will benefit the millions of gamers on Kongregate.com and the greater, still thriving, web gaming industry.”

Kongregate’s data shows that on average, about 55% of uploaded games are HTML5 games.

And we can also see that these are high-quality games, with over 60% of HTML5 titles receiving a “great” score (better than a 4.0 out of 5 rating).

In spite of this positive trend, opportunities for improvement exist. The web is an ever-evolving platform, and developers are always looking for better performance. One major request we have often heard is for multithreading support on the web. SharedArrayBuffer is a required building block for multithreading, which enables concurrently sharing memory between multiple web workers. The specification is finished, and Firefox intends to ship SharedArrayBuffer support in Firefox 55.

Another common request is for SIMD support. SIMD is short for Single Instruction, Multiple Data. It’s a way for a CPU to parallelize math instructions, offering significant performance improvements for math-heavy requirements such 3D rendering and physics.

The WebAssembly Community Group is now focused on enabling hardware parallelism with SIMD and multithreading as the next major evolutionary steps for WebAssembly. Building on the momentum of shipping the first version of WebAssembly and continued collaboration, both of these new features should be stable and ready to ship in Firefox in early 2018.

Much work has gone into optimizing runtime performance over the last few years, and with that we learned many lessons. We have collected many of these learnings in a practical blog post about porting games from native to web, and look forward to your input on other areas for improvement. As multithreading support lands in 2018, expect to see opportunities to further invest in improving memory usage.

We again wish to extend our gratitude to the game developers, publishers, engine providers, and other browsers’ engine teams who have collaborated with us over the years. We could not have done it without your help — thank you!

[syndicated profile] hacks_mozilla_feed

Posted by Jukka Jylänki

The biggest improvement this year to web performance has been the introduction of WebAssembly. Now available in Firefox and Chrome, and coming soon in Edge and WebKit, WebAssembly enables the execution of code at a low assembly-like level in the browser.

Mozilla has worked closely with the games industry for several years to reach this stage: including milestones like the release of games built with Emscripten in 2013, the preview of Unreal Engine 4 running in Firefox (2014), bringing the Unity game engine to WebGL also in 2014, exporting an indie Unity game to WebVR in 2016, and most recently, the March release of Firefox 52 with WebAssembly.

WebAssembly builds on Mozilla’s original asm.js specification, which was created to serve as a plugin-free compilation target approach for applications and games on the web. This work has accumulated a great deal of knowledge at Mozilla specific to the process of porting games and graphics technologies. If you are an engineer working on games and this sounds interesting, read on to learn more about developing games in WebAssembly.

Where Does WebAssembly Fit In?

By now web developers have probably heard about WebAssembly’s promise of performance, but for developers who have not actually used it, let’s set some context for how it works with existing technologies and what is feasible. Lin Clark has written an excellent introduction to WebAssembly. The main point is that unlike JavaScript, which is generally written by hand, WebAssembly is a compilation target, just like native assembly. Except perhaps for small snippets of code, WebAssembly is not designed to be written by humans. Typically, you’d develop the application in a source language (e.g. C/C++) and then use a compiler (e.g. Emscripten), which transforms the source code to WebAssembly in a compilation step.

This means that existing JavaScript code is not the subject of this model. If your application is written in JavaScript, then it already runs natively in a web browser, and it is not possible to somehow transform it to WebAssembly verbatim. What can be possible in these types of applications however, is to replace certain computationally intensive parts of your JavaScript with WebAssembly modules. For example, a web application might replace its JavaScript-implemented file decompression routine or a string regex routine by a WebAssembly module that does the same job, but with better performance. As another example, web pages written in JavaScript can use the Bullet physics engine compiled to WebAssembly to provide physics simulation.

Another important property: Individual WebAssembly instructions do not interleave seamlessly in between existing lines of JavaScript code; WebAssembly applications come in modules. These modules deal with low-level memory, whereas JavaScript operates on high-level object representations. This difference in structure means that data needs to undergo a transformation step—sometimes called marshalling—to convert between the two language representations. For primitive types, such as integers and floats, this step is very fast, but for more complex data types such as dictionaries or images, this can be time consuming. Therefore, replacing parts of a JavaScript application works best when applied to subroutines with large enough granularity to warrant replacement by a full WebAssembly module, so that frequent transitions between the language barriers are avoided.

As an example, in a 3D game written in three.js, one would not want to implement a small Matrix*Matrix multiplication algorithm alone in WebAssembly. The cost of marshalling a matrix data type into a WebAssembly module and then back would negate the speed performance that is gained in doing the operation in WebAssembly. Instead, to reach performance gains, one should look at implementing larger collections of computation in WebAssembly, such as image or file decompression.

On the other end of the spectrum are applications that are implemented as fully in WebAssembly as possible. This minimizes the need to marshal large amounts of data across the language barrier, and most of the application is able to run inside the WebAssembly module. Native 3D game engines such as Unity and Unreal Engine implement this approach, where one can deploy a whole game to run in WebAssembly in the browser. This will yield the best possible performance gain. However, WebAssembly is not a full replacement for JavaScript. Even if as much of the application as possible is implemented in WebAssembly, there are still parts that are implemented in JavaScript. WebAssembly code does not interact directly with existing browser APIs that are familiar to web developers, your program will call out from WebAssembly to JavaScript to interact with the browser. It is possible that this behavior will change in the future as WebAssembly evolves.

Producing WebAssembly

The largest audience currently served by WebAssembly are native C/C++ developers, who are often positioned to write performance sensitive code. An open source community project supported by Mozilla, Emscripten is a GCC/Clang-compatible compiler toolchain that allows building WebAssembly applications on the web. The main scope of Emscripten is support for the C/C++ language family, but because Emscripten is powered by LLVM, it has potential to allow other languages to compile as well. If your game is developed in C/C++ and it targets OpenGL ES 2 or 3, an Emscripten-based port to the web can be a viable approach.

Mozilla has benefited from games industry feedback – this has been a driving force shaping the development of asm.js and WebAssembly. As a result of this collaboration, Unity3D, Unreal Engine 4 and other game engines are already able to deploy content to WebAssembly. This support takes place largely under the hood in the engine, and the aim has been to make this as transparent as possible to the application.

Considerations For Porting Your Native Game

For the game developer audience, WebAssembly represents an addition to an already long list of supported target platforms (Windows, Mac, Android, Xbox, Playstation, …), rather than being a new original platform to which projects are developed from scratch. Because of this, we’ve placed a great deal of focus on development and feature parity with respect to other existing platforms in the development of Emscripten, asm.js, and WebAssembly. This parity continues to improve, although on some occasions the offered features differ noticeably, most often due to web security concerns.

The remainder of this article focuses on the most important items that developers should be aware of when getting started with WebAssembly. Some of these are successfully hidden under an abstraction if you’re using an existing game engine, but native developers using Emscripten should most certainly be aware of the following topics.

Execution Model Considerations

Most fundamental are the differences where code execution and memory model are concerned.

  • Asm.js and WebAssembly use the concept of a typed array (a contiguous linear memory buffer) that represents the low level memory address space for the application. Developers specify an initial size for this heap, and the size of the heap can grow as the application needs more memory.
  • Virtually all web APIs operate using events and an event queue mechanism to provide notifications, e.g. for keyboard and mouse input, file IO and network events. These events are all asynchronous and delivered to event handler functions. There are no polling type APIs for synchronously asking the “browser OS” for events, such as those that native platforms often provide.
  • Web browsers execute web pages on the main thread of the browser. This property carries over to WebAssembly modules, which are also executed on the main thread, unless one explicitly creates a Web Worker and runs the code there. On the main thread it is not allowed to block execution for long periods of time, since that would also block the processing of the browser itself. For C/C++ code, this means that the main thread cannot synchronously run its own loop, but must tick simulation and animation forward based on an event callback, so that execution periodically yields control back to the browser. User-launched pthreads will not have this restriction, and they are allowed to run their own blocking main loops.
  • At the time of writing, WebAssembly does not yet have multithreading support – this capability is currently in development.
  • The web security model can be a bit more strict compared to other platforms. In particular, browser APIs constrain applications from gaining direct access to low-level information about the system hardware, to mitigate being able to generate strong fingerprints to identify users. For example, it is not possible to query information such as the CPU model, the local IP address, amount of RAM or amount of available hard disk space. Additionally, many web features operate on web domain boundaries, and information traveling across domains is configured by cross-origin access control rules.
  • A special programming technique that web security also prevents is the dynamic generation and mutation of code on the fly. It is possible to generate WebAssembly modules in the browser, but after loading, WebAssembly modules are immutable and functions can no longer be added to it or changed.
  • When porting C/C++ code, standard compliant code should compile easily, but native compilers relax certain features on x86, such as unaligned memory accesses, overflowing float->int casts and invoking function pointers via signatures that mismatch from the actual type of the function. The ubiquitousness of x86 has made these kind of nonstandard code patterns somewhat common in native code, but when compiling to asm.js or WebAssembly, these types of constructs can cause issues at runtime. Refer to Emscripten documentation for more information about what kind of code is portable.

Another source of differences comes from the fact that code on a web page cannot directly access a native filesystem on the host computer, and so the filesystem solution that is provided looks a bit different than native. Emscripten defines a virtual filesystem space inside the web page, which backs onto the IndexedDB API for persistence across page visits. Browsers also store downloaded data in navigation caches, which sometimes is desirable but other times less so.

Developers should be mindful in particular about content delivery. In native application stores the model of upfront downloading and installing a large application is an expected standard, but on the web, this type of monolithic deployment model can be an off-putting user experience. Applications can download and cache a large asset package at first run, but that can cause a sizable first-time download impact. Therefore, launching with minimal amount of downloading, and streaming additional asset data as needed can be critical for building a web-friendly user experience.

Toolchain Considerations

The first technical challenge for developers comes from adapting the existing build systems to target the Emscripten compiler. To make this easier, the compiler (emcc & em++) is designed to operate closely as a drop-in replacement for GCC or Clang. This eases migration of existing build systems that are already aware of GCC-like toolchains. Emscripten supports the popular CMake build system configuration generator, and emulates support for GNU Autotools configure scripts.

A fact that is sometimes confused is that Emscripten is not a x86/ARM -> WebAssembly code transformation toolchain, but a cross-compiler. That is, Emscripten does not take existing native x86/ARM compiled code and transform that to run on the web, but instead it compiles C/C++ source code to WebAssembly. This means that you must have all the source available (or use libraries bundled with Emscripten or ported to it). Any code that depends on platform-specific (often closed source) native components, such as Win32 and Cocoa APIs, cannot be compiled, but will need to be ported to utilize other solutions.

Performance Considerations

One of the most frequently asked questions about asm.js/WebAssembly is whether it is fast enough for a particular purpose. Curiously, developers who have not yet tried out WebAssembly are the ones who most often doubt its performance. Developers who have tried it, rarely mention performance as a major issue. There are some performance caveats however, which developers should be aware of.

  • As mentioned earlier, multithreading is not available just yet, so applications that heavily depend on threads will not have the same performance available.
  • Another feature that is not yet available in WebAssembly, but planned, is SIMD instruction set support.
  • Certain instructions can be relatively slower in WebAssembly compared to native. For example, calling virtual functions or function pointers has a higher performance footprint due to sandboxing compared to native code. Likewise, exception handling is observed to cause a bigger performance impact compared to native platforms. The performance landscape can look a bit different, so paying attention to this when profiling can be helpful.
  • Web security validation is known to impact WebGL noticeably. It is recommended that applications using WebGL are careful to optimize their WebGL API calls, especially by avoiding redundant API calls, which still pay the cost for driver security validation.
  • Last, application memory usage is a particularly critical aspect to measure, especially if targeting mobile support as well. Preloading big asset packages on first run and uncompressing large amounts of audio assets are two known sources of memory bloat that are easy to do by accident. Applications will likely need to optimize specifically for this when porting, and this is an active area of optimization in WebAssembly and Emscripten runtime as well.

Summary

WebAssembly provides support for executing low-level code on the web at high performance, similar to how web plugins used to, except that web security is enforced. For developers using some of the super-popular game engines, leveraging WebAssembly will be as easy as choosing a new export target in the project build menu, and this support is available today. For native C/C++ developers, the open source Emscripten toolchain offers a drop-in compatible way to target WebAssembly. There exists a lively community of developers around Emscripten who contribute to its development, and a mailing list for discussion that can help you getting started. Games that run on the web are accessible to everyone independent of which computation platform they are on, without compromising portability, performance, or security, or requiring up front installation steps.

WebAssembly is only one part of a larger collection of APIs that power web-based games, so navigate on to the MDN games section to see the big picture. Hop right on in, and happy Emscriptening!

[syndicated profile] csstricks_feed

Posted by Chris Coyier

Stuck making "a few easy changes" to the website for someone? Component IO makes it quick and simple for you or your team to make edits (even for non-technical users).

You can manage content with a WYSIWYG editor or instantly update HTML, CSS, and JavaScript right from your website. Make changes faster, empower your team, and avoid redeployment bugs. Works with every web technology, from WordPress to Rails to React.

Join hundreds of projects already using Component IO, with a free tier and plans from $7.95/mo. It's built to make web development easier for everyone.

Try it free

Direct Link to ArticlePermalink


​Edit your website, from your website is a post from CSS-Tricks

Playing with Shadow DOM

Jul. 20th, 2017 01:44 pm
[syndicated profile] csstricks_feed

Posted by Chris Coyier

About a year ago, Twitter announced it would start displaying embedded tweets with the shadow DOM rather than an <iframe>, if the browser supports shadom DOM.

Why? Well, speed is one reason.

They say:

Much lower memory utilization in the browser, and much faster render times. Tweets will appear faster and pages will scroll more smoothly, even when displaying multiple Tweets on the same page.

Why the choice? Why is it necessary to use either iframes or shadow DOM? Why not just inject the content onto the page?

It's a totally understandable need for control. An embedded Tweet should look and behave just exactly like an embedded Tweet. They don't want to worry about the styles of the page bleeding in and messing that up.

An <iframe> makes style scoping very easy. Point the src of the iframe at a URL that displays what you want an embedded tweet to look like, and you're good. The only styles used will be those you include in that document.

Twitter does this iframe-injection in a progressive enhancement and syndication-friendly way. They provide a <blockquote> with the Tweet and a <script>. The script does the iframe-injection. If the script doesn't run, no matter, a happy blockquote. If the script does run, a fully functional embedded Tweet.

That script is the key here. Scripts can do just about anything, and they host it, so they can change it up anytime. That's what they use to detect shadow DOM support and go that route instead. And as we covered, shadow DOM is faster to render and has lower memory needs. Shadow DOM can also help with the style scoping thing, which we'll look at in a moment.

Height flexibility

There's another thing too, that happens to be near and dear to my heart. An <iframe> doesn't adjust in height to fit its contents like you expect other elements to do. You set a height and that's that. It will have scrollbars, if you allow it and the content needs it. Back in the Wufoo days, we had to jump quite a few hoops to get embedded forms (in frames) to be as tall as they needed to be. Today, at CodePen, our Embedded Pens have adjustable heights, but there isn't any option for just "as tall as they need to be". (I'm exactly sure if that makes sense for CodePen Embeds or not, but anyway, you can't do it right now.)

An element with a shadow DOM is just like any other element and that it will expand to the content naturally. I'm sure that is appealing to Twitter as well. If they calculate the height wrong, they run the risk of cutting of content or at least having the embedded Tweet look busted.

Most Basic Usage

Here's the bare minimum of how you establish a shadow DOM and put stuff in it:

See the Pen Most basic shadow DOM by Chris Coyier (@chriscoyier) on CodePen.

Notice how the styling within the Shadow DOM doesn't leak out to the regular paragraph element? Both paragraphs would be red if they did.

And notice how the paragraph inside the shadow DOM isn't sans-serif like the one outside? Well, normally that would be. Inherited styles still inherit through the shadow DOM (so in that way it's not quite as strong a barrier as an iframe). But, we're forcing it back to the initial state on purpose like this:

:host {
  all: initial;
}

Handling that fallback

My first thought for dealing with a fallback for browsers that don't support shadow DOM was that you could chuck the same exact content you were stuffing into the shadow DOM into an iframe with srcdoc, like...

<iframe srcdoc="the same content">

Or more likely this is something you're doing in JavaScript, so you'd test for support first, then either do the shadow DOM stuff or dynamically create the iframe:

See the Pen Shadow DOM Basic by Chris Coyier (@chriscoyier) on CodePen.

Turns out srcdoc isn't the best choice (alone) for a fallback as there is no IE or Edge support for it. But also that it's not too big of a deal to just use a data URL for the regular src. Here's a fork by Šime Vidas where he fixes that up:

let content = `
  <style>
    body { /* for fallback iframe */
      margin: 0;
    }
    p { 
      border: 1px solid #ccc;
      padding: 1rem;
      color: red;
      font-family: sans-serif;
    }
  </style>

  <p>Element with Shadow DOM</p>
`;

let el = document.querySelector('.my-element');

if (document.body.attachShadow) {
  
  let shadow = el.attachShadow({ mode: 'open' }); // Allows JS access inside
  shadow.innerHTML = content;
  
} else {
  
  let newiframe = document.createElement('iframe');
  'srcdoc' in newiframe ?
    newiframe.srcdoc = content :
    newiframe.src = 'data:text/html;charset=UTF-8,' + content;
  
  let parent = el.parentNode;
  parent.replaceChild(newiframe, el);

}

TL;DR

  • Shadow DOM is pretty cool.
  • It's comparable to an iframe in many ways, including style encapsulation. Embedded third-party content is a pretty good use case.
  • It's possible to use it while falling back to an iframe pretty easily.
  • It's a part of the larger world of web components, but you don't have to go all-in on all that if you don't want to.

Here's another simple demo (this one using a custom element), but instead of rolling our own back support, it's polyfilled.


Playing with Shadow DOM is a post from CSS-Tricks

Container queries

Jul. 20th, 2017 12:35 pm
[syndicated profile] adactio_feed

Every single browser maker has the same stance when it comes to features—they want to hear from developers at the coalface.

“Tell us what you want! We’re listening. We want to know which features to prioritise based on real-world feedback from developers like you.”

“How about container quer—”

“Not that.”

I don’t think it’s an exaggeration to say that literally every web developer I know would love to have container queries. If you’ve worked on any responsive project of any size, you’re bound to have bumped up against the problem of only being able to respond to viewport size, rather than the size of the containing element. Without container queries, our design systems can never be truly modular.

But there’s a divide growing between what our responsive designs need to do, and the tools CSS gives us to meet those needs. We’re making design decisions at smaller and smaller levels, but our code asks us to bind those decisions to a larger, often-irrelevant abstraction of a “page.”

But the message from browser makers has consistently been “it’s simply too hard.”

At the Frontend United conference in Athens a little while back, Jonathan gave a whole talk on the need for container queries. At the same event, Serg gave a talk on Houdini.

Now, as I understand it, Houdini is the CSS arm of the extensible web. Just as web components will allow us to create powerful new HTML without lobbying browser makers, Houdini will allow us to create powerful new CSS features without going cap-in-hand to standards bodies.

At this year’s CSS Day there were two Houdini talks. Tab gave a deep dive, and Philip talked specifically about Houdini as a breakthrough for polyfilling.

During the talks, you could send questions over Twitter that the speaker could be quizzed on afterwards. As Philip was talking, I began to tap out a question: “Could this be used to polyfill container queries?” My thumb was hovering over the tweet button at the very moment that Philip said in his talk, “This could be used to polyfill container queries.”

For that happen, browsers need to implement the layout API for Houdini. But I’m betting that browser makers will be far more receptive to calls to implement the layout API than calls for container queries directly.

Once we have that, there are two possible outcomes:

  1. We try to polyfill container queries and find out that the browser makers were right—it’s simply too hard. This certainty is itself a useful outcome.
  2. We successfully polyfill container queries, and then instead of asking browser makers to figure out implementation, we can hand it to them for standardisation.

But, as Eric Portis points out in his talk on container queries, Houdini is still a ways off (by the way, browser makers, that’s two different conference talks I’ve mentioned about container queries, just in case you were keeping track of how much developers want this).

Still, there are some CSS features that are Houdini-like in their extensibility. Custom properties feel like they could be wrangled to help with the container query problem. While it’s easy to think of custom properties as being like Sass variables, they’re much more powerful than that—the fact they can be a real-time bridge between JavaScript and CSS makes them scriptable. Alas, custom properties can’t be used in media queries but maybe some clever person can figure out a way to get the effect of container queries without a query-like syntax.

However it happens, I’d just love to see some movement on container queries. I’m not alone.

I know container queries would revolutionize my design practice, and better prepare responsive design for mobile, desktop, tablet—and whatever’s coming next.

Implementing Webmentions

Jul. 19th, 2017 06:46 pm
[syndicated profile] csstricks_feed

Posted by Chris Coyier

We get a decent amount of comments on blog posts right here on CSS-Tricks (thanks!), but I'd also say the hay day for that is over. These days, if someone writes some sort of reaction to a blog post, it could be on their own blog, or more likely, on some social media site. It makes sense. That's their home base and it's more useful to them to keep their words there.

It's a shame, though. This fragmented conversation is slightly more useful for each individual person, it's less useful as a whole. There is no canonical conversation thread. That's what Webmentions are all about, an official spec! In a sense, they allow the conversation to be dispursed but brought all together in a canonical conversation thread on the main post.

Webmentions don't need to be an alternative to comments, although when you pop over to real Drew McLellan's post you'll see he's using them that way. They can be in addition to "regular" comments. Surely the idea of turning off regular comments is appealing from a community perspective (less asshats likely when you need to link to your published words) and a technical debt perspective.

Rachel Andrew also recently implemented them, and this is classic Jeremy Keith stuff.

Direct Link to ArticlePermalink


Implementing Webmentions is a post from CSS-Tricks

[syndicated profile] hacks_mozilla_feed

Posted by Lin Clark

This is the 1st article in a 3-part series:

  1. Creating a WebAssembly module instance with JavaScript
  2. Memory in WebAssembly (and why it’s safer than you think)
  3. WebAssembly table imports… what are they?

WebAssembly is a new way of running code on the web. With it, you can write modules in languages like C or C++ and run them in the browser.

Currently modules can’t run on their own, though. This is expected to change as ES module support comes to browsers. Once that’s in place, WebAssembly modules will likely be loaded in the same way as other ES modules, e.g. using <script type="module">.

But for now, you need to use JavaScript to boot the WebAssembly module. This creates an instance of the module. Then your JavaScript code can call functions on that WebAssembly module instance.

For example, let’s look at how React would instantiate a WebAssembly module. (You can learn more in this video about how React could use WebAssembly.)

When the user loads the page, it would start in the same way.

The browser would download the JS file. In addition, a .wasm file would be fetched. That contains the WebAssembly code, which is binary.

Browser downloading a .js file and a .wasm file

We’ll need to load the code in these files in order to run it. First comes the .js file, which loads the JavaScript part of React. That JavaScript will then create an instance of a WebAssembly module… the reconciler.

To do that, it will call WebAssembly.instantiate.

React.js robot calling WebAssembly.instantiate

Let’s take a closer look at this.

The first thing we pass into WebAssembly.instantiate is going to be the binary code that we got in that .wasm file. That’s the module code.

So we extract the binary into a buffer, and then pass it in.

Binary code being passed in as the source parameter to WebAssembly.instantiate

The engine will start compiling the module code down to something that is specific to the machine that it’s running on.

But we don’t want to do this on the main thread. I’ve talked before about how the main thread is like a full stack developer because it handles JavaScript, the DOM, and layout. We don’t want to block the main thread while we compile the module. So what WebAssembly.instantiate returns is a promise.

Promise being returned as module compiles

This lets the main thread get back to its other work. The main thread knows that once the compiler is finished compiling this module, it will be notified by the promise. That promise will give it the instance.

But the compiled module is not the only thing needed to create the instance. I think of the module as kind of like an instruction book.

The instance is like a person who’s trying to make something with the instruction book. In order to make that thing, they also need raw materials. They need things that they can work with.

Instruction book next to WebAssembly robot

This is where the second parameter to WebAssembly.instantiate comes in. That is the imports object.

Arrow pointing to importObject param of WebAssembly.instantiate
I think of the imports object as a box of those raw materials, like you would get from IKEA. The instance uses these raw materials—these imports—to build a thing, as directed by the instructions. Just as an instruction manual expects a certain set of raw materials, each module expects a specific set of imports.

Imports box next to WebAssembly robot

So when you are instantiating a module, you pass it an imports object that has those imports attached to it. Each import can be one of these four kinds of imports:

  • values
  • function closures
  • memory
  • tables

Values

It can have values, which are basically global variables. The only types that WebAssembly supports right now are integers and floats, so values have to be one of those two types. That will change as more types are added in the WebAssembly spec.

Function closures

It can also have function closures. This means you can pass in JavaScript functions, which WebAssembly can then call.

This is particularly useful because in the current version of WebAssembly, you can’t call DOM methods directly. Direct DOM access is on the WebAssembly roadmap, but not part of the spec yet.

What you can do in the meantime is pass in a JavaScript function that can interact with the DOM in the way you need. Then WebAssembly can just call that JS function.

Memory

Another kind of import is the memory object. This object makes it possible for WebAssembly code to emulate manual memory management. The concept of the memory object confuses people, so I‘ve gone into a little bit more depth in another article, the next post in this series.

Tables

The final type of import is related to security as well. It’s called a table. It makes it possible for you to use something called function pointers. Again, this is kind of complicated, so I explain it in the third part of this series.

Those are the different kinds of imports that you can equip your instance with.

Different kinds of imports going into the imports box

To return the instance, the promise returned from WebAssembly.instantiate is resolved. It contains two things: the instance and, separately, the compiled module.

The nice thing about having the compiled module is that you can spin up other instances of the same module quickly. All you do is pass the module in as the source parameter. The module itself doesn’t have any state (that’s all attached to the instance). That means that instances can share the compiled module code.

Your instance is now fully equipped and ready to go. It has its instruction manual, which is the compiled code, and all of its imports. You can now call its methods.

WebAssembly robot is booted

In the next two articles, we’ll dig deeper into the memory import and the table import.

[syndicated profile] hacks_mozilla_feed

Posted by Lin Clark

This is the 2nd article in a 3-part series:

  1. Creating a WebAssembly module instance with JavaScript
  2. Memory in WebAssembly (and why it’s safer than you think)
  3. WebAssembly table imports… what are they?

Memory in WebAssembly works a little differently than it does in JavaScript. With WebAssembly, you have direct access to the raw bytes… and that worries some people. But it’s actually safer than you might think.

What is the memory object?

When a WebAssembly module is instantiated, it needs a memory object. You can either create a new WebAssembly.Memory and pass that object in. Or, if you don’t, a memory object will be created and attached to the instance automatically.

All the JS engine will do internally is create an ArrayBuffer (which I explain in another article). The ArrayBuffer is a JavaScript object that JS has a reference to. JS allocates the memory for you. You tell it how much memory are going to need, and it will create an ArrayBuffer of that size.

React.js requesting a new memory object and JS engine creating one

The indexes to the array can be treated as though they were memory addresses. And if you need more memory later, you can do something called growing to make the array larger.

Handling WebAssembly’s memory as an ArrayBuffer — as an object in JavaScript — does two things:

  1. makes it easy to pass values between JS and WebAssembly
  2. helps make the memory management safe

Passing values between JS and WebAssembly

Because this is just a JavaScript object, that means that JavaScript can also dig around in the bytes of this memory. So in this way, WebAssembly and JavaScript can share memory and pass values back and forth.

Instead of using a memory address, they use an array index to access each box.

For example, the WebAssembly could put a string in memory. It would encode it into bytes…

WebAssembly robot putting string "Hello" through decoder ring

…and then put those bytes in the array.

WebAssembly robot putting bytes into memory

Then it would return the first index, which is an integer, to JavaScript. So JavaScript can pull the bytes out and use them.

WebAssembly robot returning index of first byte in string

Now, most JavaScript doesn’t know how to work directly with bytes. So you’ll need something on the JavaScript side, like you do on the WebAssembly side, that can convert from bytes into more useful values like strings.

In some browsers, you can use the TextDecoder and TextEncoder APIs. Or you can add helper functions into your .js file. For example, a tool like Emscripten can add encoding and decoding helpers.

JS engine pulling out bytes, and React.js decoding them

So that’s the first benefit of WebAssembly memory just being a JS object. WebAssembly and JavaScript can pass values back and forth directly through memory.

Making memory access safer

There’s another benefit that comes from this WebAssembly memory just being a JavaScript object: safety. It makes things safer by helping to prevent browser-level memory leaks and providing memory isolation.

Memory leaks

As I mentioned in the article on memory management, when you manage your own memory you may forget to clear it out. This can cause the system to run out of memory.

If a WebAssembly module instance had direct access to memory, and if it forgot to clear out that memory before it went out of scope, then the browser could leak memory.

But because the memory object is just a JavaScript object, it itself is tracked by the garbage collector (even though its contents are not).

That means that when the WebAssembly instance that the memory object is attached to goes out of scope, this whole memory array can just be garbage collected.

Garbage collector cleaning up memory object

Memory isolation

When people hear that WebAssembly gives you direct access to memory, it can make them a little nervous. They think that a malicious WebAssembly module could go in and dig around in memory it shouldn’t be able to. But that isn’t the case.

The bounds of the ArrayBuffer provide a boundary. It’s a limit to what memory the WebAssembly module can touch directly.

Red arrows pointing to the boundaries of the memory object

It can directly touch the bytes that are inside of this array but it can’t see anything that’s outside the bounds of this array.

For example, any other JS objects that are in memory, like the window global, aren’t accessible to WebAssembly. That’s really important for security.

Whenever there’s a load or a store in WebAssembly, the engine does an array bounds checks to make sure that the address is inside the WebAssembly instance’s memory.

If the code tries to access an out-of-bounds address, the engine will throw an exception. This protects the rest of the memory.

WebAssembly trying to store out of bounds and being rejected

So that’s the memory import. In the next article, we’ll look at another kind of import that makes things safer… the table import.

[syndicated profile] hacks_mozilla_feed

Posted by Lin Clark

This is the 3rd article in a 3-part series:

  1. Creating a WebAssembly module instance with JavaScript
  2. Memory in WebAssembly (and why it’s safer than you think)
  3. WebAssembly table imports… what are they?

In the first article, I introduced the four different kinds of imports that a WebAssembly module instance can have:

  • values
  • function imports
  • memory
  • tables

That last one is probably a little unfamiliar. What is a table import and what is it used for?

Sometimes in a program you want to be able to have a variable that points to a function, like a callback. Then you can do things like pass it into another function.Defining a callback and passing it into a function

In C, these are called function pointers. The function lives in memory. The variable, the function pointer, just points to that memory address.

Function pointer at memory address 4 points to the callback at memory address 1

And if you need to, later you could point the variable to a different function. This should be a familiar concept.

Function pointer at memory address 4 changes to point to callback2 at memory address 4

In web pages, all functions are just JavaScript objects. And because they’re JavaScript objects, they live in memory addresses that are outside of WebAssembly’s memory.

JS function living in JS managed memory

If we want to have a variable that points to one of these functions, we need to take its address and put it into our memory.

Function pointer in WebAssembly memory pointing to function

But part of keeping web pages secure is keeping those memory addresses hidden. You don’t want code on the page to be able to see or manipulate that memory address. If there’s malicious code on the page, it can use that knowledge of where things are laid out in memory to create an exploit.

For example, it could change the memory address that you have in there, to point to a different memory location.

Then when you try and call the function, instead you would load whatever is in the memory address the attacker gave you.

Malicious actor changing the address in WebAssembly memory to point to malicious code

That could be malicious code that was inserted into memory somehow, maybe embedded inside of a string.

Tables make it possible to have function pointers, but in a way that isn’t vulnerable to these kinds of attacks.

A table is an array that lives outside of WebAssembly’s memory. The values are references to functions.

Another region of memory is added, distinct from WebAssembly memory, which contains the function pointer

Internally, these references contain memory addresses, but because it’s not inside WebAssembly’s memory, WebAssembly can’t see those addresses.

It does have access to the array indexes, though.

All memory outside of the WebAssembly memory object is obfuscated

If the WebAssembly module wants to call one of these functions, it passes the index to an operation called call_indirect. That will call the function.

call_indirect points to the first element of the obfuscated array, which in turn points to the function

Right now the use case for tables is pretty limited. They were added to the spec specifically to support these function pointers, because C and C++ rely pretty heavily on these function pointers.

Because of this, the only kinds of references that you can currently put in a table are references to functions. But as the capabilities of WebAssembly expand—for example, when direct access to the DOM is added—you’ll likely see other kinds of references being stored in tables and other operations on tables in addition to call_indirect.

Intro to Hoodie and React

Jul. 19th, 2017 01:01 pm
[syndicated profile] csstricks_feed

Posted by Jake Peyser

Let's take a look at Hoodie, the "Back-End as a Service" (BaaS) built specifically for front-end developers. I want to explain why I feel like it is a well-designed tool and deserves more exposure among the spectrum of competitors than it gets today. I've put together a demo that demonstrates some of the key features of the service, but I feel the need to first set the scene for its use case. Feel free to jump over to the demo repo if you want to get the code. Otherwise, join me for a brief overview.

Setting the Scene

It is no secret that JavaScript is eating the world these days and with its explosion in popularity, an ever-expanding ecosystem of tooling has arisen. The ease of developing a web app has skyrocketed in recent years thanks to these tools. Developer tools Prettier and ESLint give us freedom to write how we like and still output clean code. Frameworks like React and Vue provide indispensable models for creating interactive experiences. Build tools like Webpack and Babel allow us to use the latest and greatest language features and patterns without sacrificing speed and efficiency.

Much of the focus in JavaScript these days seems to be on front-end tools, but it does not mean there is no love to be found on the back-end. This same pattern of automation and abstraction is available on the server side, too, primarily in the form of what we call "Backend as a Service" (BaaS). This model provides a way for front end developers to link their web or mobile apps to backend services without the need to write server code.

Many of these services have been around for awhile, but no real winner has come forth. Parse, an early player in the space, was gobbled up by Facebook in 2013 and subsequently shut down. Firebase was acquired by Google and is slowly making headway in developing market share. Then only a few weeks ago, MongoDB announced their own BaaS, Stitch, with hopes of capitalizing on the market penetration of their DB.

BaaS Advantages

There are an overwhelming number of BaaS options, however, they all have the same primary advantages at their core.

  • Streamlined development: The obvious advantage of having no custom server is that it removes the need to develop one! This means your development team will perform less context switching and ultimately have more time to focus on core logic. No server language knowledge required!
  • No boilerplate servers: Many servers end up existing for the sole purpose of connecting a client with relevant data. This often results in massive amounts of web framework and DAL boilerplate code. The BaaS model removes the need for this repetitive code.

These are just the main advantages of BaaS. Hoodie provides these and many more unique capabilities that we will walk through in the next section.

Try on your Hoodie

To demonstrate some of the out-of-the-box functionality provided by Hoodie, I am going to walk you through a few pieces of a simple Markdown note taking web application. It is going to handle user authentication, full CRUD of users' notes, and the ability to keep working even when a connection to the internet is lost.

You can follow along with the code by cloning the hoodie-notes GitHub repository to your local machine and running it using the directions in the README.

This walkthrough is meant to focus on the implementation of the hoodie-client and thus, assumes prior knowledge of React, Redux, and ES6. Knowledge of these, although helpful, is not necessary to understand the scope of what we will discuss here.

The Basics

There are really only three things you have to do to get started with Hoodie.

  1. Place your static files in a folder called /public at the root of your project. We place our index.html and all transpiled JS and image files here so they can be exposed to clients.
  2. Initialize the Hoodie client in your front end code:

    const hoodie = new Hoodie({
      url: window.location.origin,
      PouchDB: require('pouchdb-browser')
    })
  3. Start your hoodie server by running hoodie in the terminal

Of course, there is more to creating the app, but that is all you really need to get started!

User Auth

Hoodie makes user and session management incredibly simple. The Account API can be used to create users, manage their login sessions, and update their accounts. All code handling these API calls is stored in the user reducer.

When our app starts up, we see a login screen with the option to create a user or log in.

When either of these buttons are pressed, the corresponding Redux thunk is dispatched to handle the authentication. We use the signUp and signIn functions to handle these events. To create a new account, we make the following call:

hoodie.account.signUp({ username: 'guest', password: '1234' })
  .then(account => {
    // successful creation
  }).catch(err => {
    // account creation failure
  })

Once we have an account in the system, we can login in the future with:

hoodie.account.signIn({ username: 'guest', password: '1234' })
  .then(account => {
    // successful login
  }).catch(err => {
    // login failure
  })

We now have user authentication, authorization, and session management without writing a single line of server code. To add a cherry on top, Hoodie manages sessions in local storage, meaning that you can refresh the page without the need to log back in. To leverage this, we can execute the following logic the initial rendering of our app:

hoodie.account.get()
  .then({ session, username }=> {
    if (session)
      console.log(`${username} is already logged in!`)
  }).catch(err => {
    // session check failure
  })

And to logout we only need to call hoodie.account.signOut(). Cool!

CRUD Notes

Perhaps the nicest thing about user management in Hoodie is that all documents created while logged in are only accessible by that authenticated user. Authorization is entirely abstracted from us, allowing us to focus on the simple logic of creating, retrieving, updating, and deleting documents using the Store API. All code handling these API calls is stored in the notes reducer.

Let's start off with creating a new note:

hoodie.store.add({ title: '', text: '' })
  .then(note => console.log(note))
  .catch(err => console.error(err))

We can pass any object we would like to the add function, but here we create an empty note with a title and text field. In return, we are given a new object in the Hoodie datastore with its corresponding unique ID and the properties we gave it.

When we want to update that document, it is as simple as passing that same note back in with the updated (or even new) properties:

hoodie.store.update(note)
  .then(note => console.log(note))
  .catch(err => console.error(err))

Hoodie handles all the diffing and associated logic that it takes to update the store. All we need to do is pass in the note to the update function. Then, when the user elects to delete that note, we pass its ID to the remove function:

hoodie.store.remove(note._id)
  .then(()=> console.log(`Removed note ${note._id}`))
  .catch(err => console.error(err))

The last thing we need to do is retrieve our notes when the user logs back in. Since we are only storing notes in the datastore, we can go ahead and retrieve all of the user's documents with the findAll function:

hoodie.store.findAll()
  .then(notes => console.log(notes))
  .catch(err => console.error(err))

If we wanted, we could use the find function to look up individual documents as well.

Putting all of these calls together, we've essentially replaced a /notes REST API endpoint that otherwise would have required a fair amount of boilerplate request handling and DAL code. You might say this is lazy, but I'd say we are working smart!

Monitoring the connection status

Hoodie was built with an offline-first mentality, meaning that it assumes that clients will be offline for extended periods of time during their session. This attitude prioritizes the handling of these events such that it does not produce errors, but instead allows users to keep working as usual without fear of data loss. This functionality is enabled under the hood by PouchDB and a clever syncing strategy, however, the developer using the hoodie-client does not need to be privy to this as it is all handled behind the scenes.

We'll see how this improves our user experience in a bit, but first let's see how we can monitor this connection using the Connection Status API. When the app first renders, we can establish listeners for our connection status on the root component like so:

componentDidMount() {
  hoodie.connectionStatus.startChecking({interval: 3000})
  hoodie.connectionStatus.on('disconnect', () => this.props.updateStatus(false))
  hoodie.connectionStatus.on('reconnect', () => this.props.updateStatus(true))
}

In this case, we tell Hoodie to periodically check our connection status and then attach two listeners to handle changes in connections. When either of these events fire, we update the corresponding value in our Redux store and adjust the connection indicator in the UI accordingly. This is all the code we need to alert the user that they have lost a connection to our server.

To test this, open up the app in a browser. You'll see the connection indicator in the top left of the app. If you stop the server while the page is still open, you will see the status change to "Disconnected" on the next interval.

While you are disconnected, you can continue to add, edit, and remove notes as you would otherwise. Changes are stored locally and Hoodie keeps track of the changes that are made while you are offline.

Once you're ready, turn the server back on and the indicator will once again change back to "Connected" status. Hoodie then syncs with the server in the background and the user is none the wiser about the lapse of connectivity (outside of our indicator, of course).

If you don't believe it's that easy, go ahead and refresh your page. You'll see that the data you created while offline is all there, as if you never lost the connection. Pretty incredible stuff considering we did nothing to make it happen!

Why I Like Hoodie

Hoodie is not the only BaaS offering by any means, but I consider it a great option for several reasons

  1. Simple API: In this walkthrough, we were able to cover 3 out of 4 of the Hoodie APIs. They are incredibly simple, without much superfluous functionality. I am a big fan of simplicity over complexity until the latter cannot be avoided and Hoodie definitely fits that bill.
  2. Free and self-hosted: Putting Hoodie into production yourself can seem like a drag, but I believe such a service gives you long-term assurance. Paid, hosted services require a bet on that service's reliability and longevity (see: Parse). This, along with vendor lock-in, keep me on the side of self-hosting when it makes sense.
  3. Open Source: No explanation needed here...support the OSS community!
  4. Offline-first: Hoodie provides a seamless solution to the relevant problem of intermittent connectivity and removes the burden of implementation from developers.
  5. Plugins: Hoodie supports 3rd party plugins to provide support for additional server-side functionality outside the scope of the API. It allows for some clever solutions when you begin to miss the flexibility of having your own server.
  6. Philosophy: The developers who built and support Hoodie have clearly thought hard about what the service represents and why they built it. Their promotion of openness, empowerment, and decentralization (among other things) is great to see at the core of an open source project. I love everything about this!

Considerations

Before you make the call to cut ties with your server in favor of a BaaS like Hoodie, there are some things you should consider.

Do you favor increased development speed or future flexibility? If the former is your priority, then go with a BaaS! If you really care about performance and scale, you're probably better off spinning up your own server(s). This points toward using a BaaS for an MVP or light-weight app and creating a custom server for well-defined, complex applications.

Does your app require integration with any 3rd party services? If so, it is likely you will need the flexibility of your own server for implementing your own custom implementation logic rather than constrain yourself to a Hoodie plugin.

Lastly, the documentation for Hoodie is severely lacking. It will help you get started, but many API definitions are missing from the docs and you will have to fill in some of the blanks yourself. This is mitigated by the fact that the interface is extremely well thought out. Nonetheless, it makes for a frustrating experience if you are used to complete documentation.

Conclusion

For front end developers, using a BaaS is a great prospect when considering your options for creating a web application. It avoids the need for writing server logic and implementing what essentially amounts to a boilerplate REST API. Hoodie delivers this possibility, with the added bonus of a clean interface, simple user management, and offline-first capabilities.

If all you need is a simple CRUD application, consider using Hoodie for your next app!

Additional Resources


Intro to Hoodie and React is a post from CSS-Tricks

The magical and the mundane

Jul. 19th, 2017 10:53 am
[syndicated profile] adactio_feed

The iPhone—and by extension, the smartphone—is a decade old. Ian Bogost has written an interesting piece in The Atlantic charting our changing relationship with the technology.

First, it was like a toy dog:

A device that could be cared for, and conspicuously so.

Then, it was like a cigarette:

A nervous tic, facilitated by a handheld apparatus that releases relief when operated.

Later, it was like a rosary:

Its toy-dog quirks having been tamed, its compulsive nature having been accepted, the iPhone became the magic wand by which all worldly actions could be performed, all possible information acquired.

Finally, it simply becomes …a rectangle.

Abstract, as a shape. Flat, as a surface. But suggestive of so much. A table for community. A door for entry, or for exit. A window for looking out of, or a picture for looking into. A movie screen for distraction, or a cradle for comfort, or a bed for seduction.

Design dissolves in behaviour. This is something that Ben wrote about recently in his excellent Slapdashery series: “Everything’s amazing and nobody’s happy.”

Technology tweaks our desire for novelty; but as soon as we get it we’re usually bored. There are no technologies that I can think of that haven’t become mundane.

This is something I touched on in my talk last year at An Event Apart. There’s a thread throughout the talk about Arthur C. Clarke, and of course I quote his third law:

Any sufficiently advanced technology is indistinguishable from magic.

I propose an addendum to that:

Any sufficiently advanced technology is indistinguishable from magic at first.

The magical quickly becomes the mundane. That’s exactly the point that Louis CK is making in the piece that Ben references.

Seven years ago Frank wrote his wonderful essay There Is A Horse In The Apple Store:

I have a term called a “tiny pony.” It is a thing that is exceptional that no one, for whatever reason, notices. Or, conversely, it is an exceptional thing that everyone notices, but quickly grows acclimated to despite the brilliance of it all.

We are surrounded by magical tiny ponies. I mean, just think: right now you are reading some words at a URL on the World Wide Web. Even more magically, I just published some words at my own URL on the World Wide Web. That still blows my mind! I hope I never lose that feeling.

Start with empathy

Jul. 18th, 2017 05:54 pm
[syndicated profile] simplyaccessible_feed

Posted by Caryn Pagel

The world of digital accessibility is laden with the language of compliance, inclusive design, clean code, and screen readers. So much so that sometimes we forget what really lies beneath our work in accessibility. Why do we do what we do? How do we get people on board with creating accessible sites, products, and services? The answer to these can be found in one word: empathy.

As designers and developers, it’s essential that we include empathy in all our decisions. If your software is not usable for some or all of your users, why are you making it? The people who use your software are the reason you’re making it. You’re not a jerk – we can tell. If you understood how people with disabilities encounter (and sometimes struggle with) your website or application, you’d want to fix it. The more you understand, the greater the empathy you will have.

Foundational empathy

a young woman works at two Apple desktop computersThe very first time I observed a person using a screen reader with a web product I had designed, my jaw dropped. I couldn’t believe what I was seeing. She was unable to perform an essential function of the product, and she thought she was doing something wrong. As I’m fully sighted, I could see the solution right in front of my face, but she had no way of navigating to it. Ever since that day, I’ve been advocating for including accessibility in design and development practices. In my time at Simply Accessible, I’ve observed many more usability sessions with people of varying abilities, but I’ll never forget that first time. It was life-changing for me.

As defined by Merriam-Webster, empathy is the capacity for understanding, being aware of, being sensitive to, and vicariously experiencing the feelings, thoughts, and experience of another of either the past or present without having the feelings, thoughts, and experience fully communicated in an objectively explicit manner.

Everyone on the Simply Accessible team spends our days being aware of and sensitive to the needs and wants of users. We pay particular attention to how varying abilities may change those needs and wants. For example, when a modal window appears on a page, and keyboard focus is not moved into the modal, a person who only uses a keyboard who is sighted will see the modal, but will not be able to access any interactive elements within it, or close the window. The same issue affects non-sighted people who use a screen reader in a different way – they will select the link to open the modal, but they won’t know it opened at all, and they cannot read any of the content. In this example, the root and the solution of the issue are the same, but the issue experienced is different, depending on ability.

You may think it’s awareness and technical knowledge that fixes a situation like that, and you’d be right. But beneath that awareness is always empathy.

Show me an accessible website, product or service, and more often than not you are showing me a designer or developer who cares, deeply, about the user experience.

Inclusive empathy

two women looking at a Mac desktop computer monitorWe had just started reviewing issues that we had reported on their website. I could tell by the question that our client was overwhelmed and didn’t know where to begin. I could also tell she was feeling defeated, and we hadn’t even begun solving her company’s accessibility issues. I feared they were ready to throw in the towel, and we’d really only just gotten the towel out.

“What do you think about creating a separate website for our users with disabilities?” the client asked me, not five minutes into our review session.

I knew we needed to find a way to calm their fears and restore their confidence. I also knew they needed to get their accessibility issues resolved–and soon.

The empathy came out in full force–this time, for the client. As a team, we worked with them on a custom approach to get their own development team started.

Flash forward to today, and their development team is in full swing, well on their way to making their website a welcoming experience for all–no separate website required.

The empathy that’s part of our everyday work at Simply Accessible extends to how we approach our clients. Our clients’ desire to work with us is due to varying motivations. Some are overwhelmed. Some are scared. Most don’t know where to begin. But all have a problem they need solved. We need to understand where each client is coming from, and include empathy in our work with them, for them.

Expansive empathy

When working with clients, we encourage them to expand their own empathy for their users with disabilities. We do this by simply explaining what kinds of issues may happen on their website/app, and what steps people need to take to remedy the issue (if possible). We can tell our clients which technical standard or best practice that they are not complying with until we’re blue in the face, but it’s always the real-life user stories that get through to people.

When we see a group of <a> anchor tags without valid href attributes, there are several ways we could choose to report the issue to our client:

  • The links on the page are not keyboard accessible.
  • The links on the page do not comply with WCAG success criterion “2.1.1 Keyboard.”
  • People with mobility/dexterity issues, who rely on a keyboard, are not able to select the links, because they are not keyboard accessible.

Our team will always choose the third option, explaining what a real user will experience. When you understand the reality your users are facing, you will be motivated to create better site experiences for everyone. By helping our clients in this way, we’re expanding our empathy to include them, which inevitably ripples out to affect their users in a deeper and more attuned way.

The best we can be

five fists bumping together over a deskThe next time you’re engaged in a discussion about accessibility and it doesn’t budge beyond the technical, remember that beneath it all is empathy. The more empathy we have, the better we become at making things accessible. The more awareness we build by demonstrating to clients the need for accessible sites, products, and services. The more understanding we are when working with clients who might be overwhelmed as they start their accessibility journey. And, the more effective our clients become at creating sites, products, and services that meet the needs of everyone.

Upping the empathy quotient among decision-makers, designers, and developers is integral to ensuring the creation of a digital world for everyone.

 

 

The post Start with empathy appeared first on Simply Accessible.

Profile

carene_waterman: An image of the Carina Nebula (Default)
carene_waterman

July 2014

S M T W T F S
  12345
6789101112
13141516171819
2021 22 2324 2526
2728293031  

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jul. 26th, 2017 12:36 am
Powered by Dreamwidth Studios