Tag Archives: these

Thumbnail

A Strategy Guide To CSS Custom Properties




A Strategy Guide To CSS Custom Properties

Michael Riethmuller



CSS Custom Properties (sometimes known as ‘CSS variables’) are now supported in all modern browsers, and people are starting to use them in production. This is great, but they’re different from variables in preprocessors, and I’ve already seen many examples of people using them without considering what advantages they offer.

Custom properties have a huge potential to change how we write and structure CSS and to a lesser extent, how we use JavaScript to interact with UI components. I’m not going to focus on the syntax and how they work (for that I recommend you read “It’s Time To Start Using Custom Properties”). Instead, I want to take a deeper look at strategies for getting the most out of CSS Custom Properties.

How Are They Similar To Variables In Preprocessors?

Custom Properties are a little bit like variables in preprocessors but have very some important differences. The first and most obvious difference is the syntax.

With SCSS we use a dollar symbol to denote a variable:

$smashing-red: #d33a2c;

In Less we use an @ symbol:

@smashing-red: #d33a2c;

Custom properties follow a similar conventions and use a -- prefix:

:root  --smashing-red: #d33a2c; 
.smashing-text  
  color: var(--smashing-red);

One important difference between custom properties and variables in preprocessors is that custom properties have a different syntax for assigning a value and retrieving that value. When retrieving the value of a custom property we use the var() function.

The next most obvious difference is in the name. They are called ‘custom properties’ because they really are CSS properties. In preprocessors, you can declare and use variables almost anywhere, including outside declaration blocks, in media rules, or even as part of a selector.

$breakpoint: 800px;
$smashing-red: #d33a2c;
$smashing-things: ".smashing-text, .cats";

@media screen and (min-width: $breakpoint) 
  #$smashing-things 
    color: $smashing-red;
  
}

Most of the examples above would be invalid using custom properties.

Custom properties have the same rules about where they can be used as normal CSS properties. It’s far better to think of them as dynamic properties than variables. That means they can only be used inside a declaration block, or in other words, custom properties are tied to a selector. This can be the :root selector, or any other valid selector.

:root  --smashing-red: #d33a2c; 

@media screen and (min-width: 800px) 
  .smashing-text, .cats 
    --margin-left:  1em;
  
}

You can retrieve the value of a custom property anywhere you would otherwise use a value in a property declaration. This means they can be used as a single value, as part of a shorthand statement or even inside calc() equations.

.smashing-text, .cats 
  color: var(--smashing-red);
  margin: 0 var(--margin-horizontal);
  padding: calc(var(--margin-horizontal) / 2)

However, they cannot be used in media rules, or selectors including :nth-child().

There is probably a lot more you want to know about the syntax and how custom properties work, such as how to use fallback values and can you assign variables to other variables (yes), but this basic introduction should be enough to understand the rest of the concepts in this article. For more information on the specifics of how custom properties work, you can read “It’s Time To Start Using Custom Properties” written by Serg Hospodarets.

Dynamic vs. Static

Cosmetic differences aside, the most significant difference between variables in preprocessors and custom properties is how they are scoped. We can refer to variables as either statically or dynamically scoped. Variables in preprocessors are static whereas custom properties are dynamic.

Where CSS is concerned static means that you can update the value of a variable at different points in the compilation process, but this cannot change the value of the code that came before it.

$background: blue;
.blue 
  background: $background;

$background: red;
.red 
  background: $background;

results in:

.blue 
  background: blue;

.red 
  background: red;

Once this is rendered to CSS, the variables are gone. This means that we could potentially read an .scss file and determine it’s output without knowing anything about the HTML, browser or other inputs. This is not the case with custom properties.

Preprocessors do have a kind of “block scope” where variables can be temporarily changed inside a selector, function or mixin. This changes the value of a variable inside the block, but it’s still static. This is tied to the block, not the selector. In the example below, the variable $background is changed inside the .example block. It changes back to the initial value outside the block, even if we use the same selector.

$background: red;
.example 
  $background: blue;
  background: $background;


.example 
  background: $background;

This will result in:

.example 
  background: blue;

.example 
  background: red;

Custom properties work differently. Where custom properties are concerned, dynamically scoped means they are subject to inheritance and the cascade. The property is tied to a selector and if the value changes, this affects all matching DOM elements just like any other CSS property.

This is great because you can change the value of a custom property inside a media query, with a pseudo selector such as hover, or even with JavaScript.

a 
  --link-color: black;

a:hover,
a:focus 
  --link-color: tomato;

@media screen and (min-width: 600px) 
  a 
    --link-color: blue;
  
}

a 
  color: var(--link-color);

We don’t have to change where the custom property is used — we change the value of the custom property with CSS. This means using the same custom property, we can have different values in different places or context on the same page.

Global vs. Local

In addition to being static or dynamic, variables can also be either global or local. If you write JavaScript, you will be familiar with this. Variables can either be applied to everything inside an application, or their scope can be limited to specific functions or blocks of code.

CSS is similar. We have some things that are applied globally and some things that are more local. Brand colors, vertical spacing, and typography are all examples of things you might want to be applied globally and consistently across your website or application. We also have local things. For example, a button component might have a small and large variant. You wouldn’t want the sizes from these buttons to be applied to all input elements or even every element on the page.

This is something we are familiar with in CSS. We’ve developed design systems, naming conventions and JavaScript libraries, all to help with isolating local components and global design elements. Custom properties provide new options for dealing with this old problem.

CSS Custom Properties are by default locally scoped to the specific selectors we apply them to. So they are kinda like local variables. However, custom properties are also inherited, so in many situations they behave like global variables — especially when applied to the :root selector. This means that we need to be thoughtful about how to use them.

So many examples show custom properties being applied to the :root element and although, this fine for a demo, it can result in a messy global scope and unintended issues with inheritance. Luckily, we’ve already learned these lessons.

Global Variables Tend To Be Static

There are a few small exceptions, but generally speaking, most global things in CSS are also static.

Global variables like brand colors, typography and spacing don’t tend to change much from one component to the next. When they do change this tends to be a global rebranding or some other significant change that rarely happens on a mature product. It still makes sense for these things to be variables, they are used in many places, and variables help with consistency. But it doesn’t make sense for them to be dynamic. The value of these variables does not change in any dynamic way.

For this reason, I strongly recommend using preprocessors for global (static) variables. This not only ensures that they are always static, but it visually denotes them within the code. This can make CSS a whole lot more readable and easier to maintain.

Local Static Variables Are OK (Sometimes)

You might think given the strong stance on global variables being static, that by reflection, all local variables might need to be dynamic. While it’s true that local variables do tend to be dynamic, this is nowhere near as strong as the tendency for a global variable to be static.

Locally static variables are perfectly OK in many situations. I use preprocessors variables in component files mostly as a developer convenience.

Consider the classic example of a button component with multiple size variations.


buttons

My scss might look something like this:

$button-sml: 1em;
$button-med: 1.5em;
$button-lrg: 2em;

.btn 
  // Visual styles


.btn-sml 
  font-size: $button-sml;


.btn-med 
  font-size: $button-med;


.btn-lrg 
  font-size: $button-lrg;

Obviously, this example would make more sense if I was using the variables multiple times or deriving margin and padding values from the size variables. However, the ability to quickly prototype different sizes might be a sufficient reason.

Because most static variables are global, I like to differentiate static variables that are used only inside a component. To do this, you can prefix these variables with the component name, or you could use another prefix such as c-variable-name for component or l-variable-name for local. You can use whatever prefix you want, or you can prefix global variables. Whatever you choose, it’s helpful to differentiate especially if converting an existing codebase to use custom properties.

When To Use Custom Properties

If it is alright to use static variables inside components, when should we use custom properties? Converting existing preprocessor variables to custom properties usually makes little sense. After all, the reason for custom properties is completely different. Custom properties make sense when we have CSS properties that change relative to a condition in the DOM — especially a dynamic condition such as :focus, :hover, media queries or with JavaScript.

I suspect we will always use some form of static variables, although we might need fewer in future, as custom properties offer new ways to organise logic and code. Until then, I think in most situations we are going to be working with a combination of preprocessor variables and custom properties.

It’s helpful to know that we can assign static variables to custom properties. Whether they are global or local, it makes sense in many situations to convert static variables, to locally dynamic custom properties.

Note: Did you know that $var is valid value for a custom property? Recent versions of Sass recognize this, and therefore we need to interpolate variables assigned to custom properties, like this: #$var. This tells Sass you want to output the value of the variable, rather than just $var in the stylesheet. This is only needed for situations like custom properties, where a variable names can also be a valid CSS.

If we take the button example above and decide all buttons should use the small variation on mobile devices, regardless of the class applied in the HTML, this is now a more dynamic situation. For this, we should use custom properties.

$button-sml: 1em;
$button-med: 1.5em;
$button-lrg: 2em;

.btn 
  --button-size: #$button-sml;
}

@media screen and (min-width: 600px) 
  .btn-med 
    --button-size: #$button-med;
  }
  .btn-lrg 
    --button-size: #$button-lrg;
  }
}

.btn 
  font-size: var(--button-size);

Here I create a single custom property: --button-size. This custom property is initially scoped to all button elements using the btn class. I then change the value of --button-size above 600px for the classes btn-med and btn-lrg. Finally, I apply this custom property to all button elements in one place.

Don’t Be Too Clever

The dynamic nature of custom properties allows us to create some clever and complicated components.

With the introduction of preprocessors, many of us created libraries with clever abstractions using mixins and custom functions. In limited cases, examples like this are still useful today, but for the most part, the longer I work with preprocessors the fewer features I use. Today, I use preprocessors almost exclusively for static variables.

Custom properties will not (and should not) be immune from this type of experimentation, and I look forward to seeing many clever examples. But in the long run, readable and maintainable code will always win over clever abstractions (at least in production).

I read an excellent article on this topic on the Free Code Camp Medium recently. It was written by Bill Sourour and is called “Don’t Do It At Runtime. Do It At Design Time.” Rather than paraphrasing his arguments, I’ll let you read it.

One key difference between preprocessor variables and custom properties is that custom properties work at runtime. This means things that might have been borderline acceptable, in terms of complexity, with preprocessors might not be a good idea with custom properties.

One example that illustrated this for me recently was this:

:root 
  --font-scale: 1.2;
  --font-size-1: calc(var(--font-scale) * var(--font-size-2));
  --font-size-2: calc(var(--font-scale) * var(--font-size-3)); 
  --font-size-3: calc(var(--font-scale) * var(--font-size-4));   
  --font-size-4: 1rem;     

This generates a modular scale. A modular scale is a series of numbers that relate to each other using a ratio. They are often used in web design and development to set font-sizes or spacing.

In this example, each custom property is determined using calc(), by taking the value of the previous custom property and multiplying this by the ratio. Doing this, we can get the next number in the scale.

This means the ratios are calculated at run-time and you can change them by updating only the value of the --font-scale property. For example:

@media screen and (min-width: 800px) 
  :root 
    --font-scale: 1.33;
  
}

This is clever, concise and much quicker than calculating all the values again should you want to change the scale. It’s also something I would not do in production code.

Although the above example is useful for prototyping, in production, I’d much prefer to see something like this:

:root 
  --font-size-1: 1.728rem;
  --font-size-2: 1.44rem;
  --font-size-3: 1.2em;
  --font-size-4: 1em;


@media screen and (min-width: 800px) 
  :root 
    --font-size-1: 2.369rem; 
    --font-size-2: 1.777rem;     
    --font-size-3: 1.333rem; 
    --font-size-4: 1rem;     
  
}

Similar to the example in Bill’s article, I find it helpful to see what the actual values are. We read code many more times than we write it and global values such as font scales change infrequently in production.

The above example is still not perfect. It violates the rule from earlier that global values should be static. I’d much prefer to use preprocessor variables and convert them to locally dynamic custom properties using the techniques demonstrated earlier.

It is also important to avoid situations where we go from using one custom property to a different custom property. This can happen when we name properties like this.

Change The Value Not The Variable

Change the value not the variable is one of the most important strategies for using custom properties effectively.

As a general rule, you should never change which custom property is used for any single purpose.
It’s easy to do because this is exactly how we do things with preprocessors, but it makes little sense with custom properties.

In this example, we have two custom properties that are used on an example component. I switch from using the value of --font-size-small to --font-size-large depending on the screen size.

:root 
  --font-size-small: 1.2em;
  --font-size-large: 2em;            

.example 
  font-size: var(--font-size-small);

@media screen and (min-width: 800px) 
  .example 
    font-size: var(--font-size-large);
  
}

A better way to do this would be to define a single custom property scoped to the component. Then using a media query, or any other selector, change its value.

.example 
  --example-font-size: 1.2em;

@media screen and (min-width: 800px)                              
  .example 
    --example-font-size: 2em;            
  
}

Finally, in a single place, I use the value of this custom property:

.example 
  font-size: var(--example-font-size);

In this example and others before it, media queries have only been used to change the value of custom properties. You might also notice there is only one place where the var() statement is used, and regular CSS properties are updated.

This separation between variable declarations and property declarations is intentional. There are many reasons for this, but the benefits are most obvious when thinking about responsive design.

Responsive Design With Custom Properties

One of the difficulties with responsive design when it relies heavily on media queries is that the no matter how you organize your CSS, styles relating to a particular component become fragmented across the stylesheet.

It can be very difficult to know what CSS properties are going to change. Still, CSS Custom Properties can help us organize some of the logic related to responsive design and make working with media queries a lot easier.

If It Changes It’s A Variable

Properties that change using media queries are inherently dynamic and custom properties provide the means to express dynamic values in CSS. This means that if you are using a media query to change any CSS property, you should place this value in a custom property.

You can then move this, along with all the media rules, hover states or any dynamic selectors that define how the value changes, to the top of the document.

Separate Logic From Design

When done correctly, separation of logic and design means that media queries are only be used to change the value of custom properties. It means all the logic related to responsive design should be at the top of the document, and wherever we see a var() statement in our CSS, we immediately know that this property that changes. With traditional methods of writing CSS, there was no way of knowing this at a glance.

Many of us got very good at reading and interpreting CSS at a glance while tracking in our head which properties changed in different situations. I’m tired of this, and I don’t want to do this anymore! Custom properties now provide a link between logic and its implementation, so we don’t need to track this, and that is incredibly useful!

The Logic Fold

The idea of declaring variables at the top of a document or function is not a new idea. It’s something we do in most languages, and it’s now something we can do in CSS as well. Writing CSS in this way creates a clear visual distinction between CSS at the top of the document and below. I need a way to differentiate these sections when I talk about them and the idea of a “logic fold” is a metaphor I’ve started using.
Above the fold contains all preprocessor variables and custom properties. This includes all the different values a custom property can have. It should be easy to trace how a custom property changes.

CSS below the fold is straightforward and highly declarative and easy to read. It feels like CSS before media queries and other necessary complexities of modern CSS.

Take a look at a really simple example of a six column flexbox grid system:

.row 
  --row-display: block;

@media screen and (min-width: 600px) 
  .row 
    --row-display: flex;
  
}

The --row-display custom property is initially set to block. Above 800px the display mode is set to flex.

Below the fold might look like this:

.row 
  display: var(--row-display);
  flex-direction: row;
  flex-wrap: nowrap;

.col-1, .col-2, .col-3,
.col-4, .col-5, .col-6 
  flex-grow: 0;
  flex-shrink: 0;

.col-1  flex-basis: 16.66%; 
.col-2  flex-basis: 33.33%; 
.col-3  flex-basis: 50%; 
.col-4  flex-basis: 66.66%; 
.col-5  flex-basis: 83.33%; 
.col-6  flex-basis: 100%; 

We immediately know --row-display is a value that changes. Initially, it will be block, so the flex values will be ignored.

This example is fairly simple, but if we expanded it to include a flexible width column that fills the remaining space, it’s likely flex-grow, flex-shrink and flex-basis values would need to be converted to custom properties. You can try this or take a look at a more detailed example here.

Custom Properties For Theming

I’ve mostly argued against using custom properties for global dynamic variables and hopefully implied that attaching custom properties to the :root selector is in many cases considered harmful. But every rule has an exception, and for custom properties, it’s theming.

Limited use of global custom properties can make theming a whole lot easier.

Theming generally refers to letting users customize the UI in some way. This could be something like changing colors on a profile page. Or it might be something more localized. For example, you can choose the color of a note in the Google Keep application.


Google Keep App

Theming usually involves compiling a separate stylesheet to override a default value with user preferences, or compiling a different stylesheet for each user. Both of these can be difficult and have an impact on performance.

With custom properties, we don’t need to compile a different stylesheet; we only need to update the value of properties according to the user’s preferences. Since they are inherited values, if we do this on the root element they can be used anywhere in our application.

Capitalize Global Dynamic Properties

Custom properties are case sensitive and since most custom properties will be local, if you are using global dynamic properties, it can make sense to capitalize them.

:root 
  --THEME-COLOR: var(--user-theme-color, #d33a2c);            

Capitalization of variables often signifies global constants. For us, this is going to signify that the property is set elsewhere in the application and that we should probably not change it locally.

Avoid Directly Setting Global Dynamic Properties

Custom properties accept a fallback value. It can be a useful to avoid directly overwriting the value of a global custom properties and keep user values separate. We can use the fallback value to do this.

The example above sets the value of --THEME-COLOR to the value of --user-theme-color if it exists. If --user-theme-color is not set, the value of #d33a2c will be used. This way, we don’t need to provide a fallback every time we use --THEME-COLOR.

You might expect in the example below that the background will be set to green. However, the value of --user-theme-color has not been set on the root element, so the value of --THEME-COLOR has not changed.

:root 
  --THEME-COLOR: var(--user-theme-color, #d33a2c);            

body 
  --user-theme-color: green;
  background: var(--THEME-COLOR);

Indirectly setting global dynamic properties like this protects them from being overwritten locally and ensures user settings are always inherited from the root element. This is a useful convention to safeguard your theme values and avoid unintended inheritance.

If we do want to expose specific properties to inheritance, we can replace the :root selector with a * selector:

:root 
  --THEME-COLOR: var(--user-theme-color, #d33a2c);            

body 
  --user-theme-color: green;
  background: var(--THEME-COLOR);

Now the value of --THEME-COLOR is recalculated for every element and therefore the local value of --user-theme-color can be used. In other words, the background color in this example will be green.

You can see some more detailed examples of this pattern in the section on Manipulating Color With Custom Properties.

Updating Custom Properties With JavaScript

If you want to set custom properties using JavaScript there is a fairly simple API and it looks like this:

const elm = document.documentElement;
elm.style.setProperty('--USER-THEME-COLOR', 'tomato');

Here I’m setting the value of --USER-THEME-COLOR on the document element, or in other words, the :root element where it will be inherited by all elements.

This is not a new API; it’s the same JavaScript method for updating styles on an element. These are inline styles so they will have a higher specificity than regular CSS.

This means it’s easy to apply local customizations:

.note 
  --note-color: #eaeaea;

.note 
  background: var(--note-color);

Here I set a default value for --note-color and scope this to the .note component. I keep the variable declaration separate from the property declaration, even in this simple example.

const elm = document.querySelector('#note-uid');
elm.style.setProperty('--note-color', 'yellow');

I then target a specific instance of a .note element and change the value of the --note-color custom property for that element only. This will now have higher specificity than the default value.

You can see how this works with this example using React. These user preferences could be saved in local storage or in the case of a larger application perhaps in a database.

Manipulating Color With Custom Properties

In addition to hex values and named colors, CSS has colors function such as rgb() and hsl(). These allow us to specify individual components of a color such as the hue or lightness. Custom properties can be used in conjunction with color functions.

:root 
  --hue: 25;

body 
  background: hsl(var(--hue), 80%, 50%);

This is useful, but some of the most widely used features of preprocessors are advanced color functions that allow us to manipulate color using functions like lighten, darken or desaturate:

darken($base-color, 10%);
lighten($base-color, 10%);
desaturate($base-color, 20%);

It would be useful to have some of these features in browsers. They are coming, but until we have native color modification functions in CSS, custom properties could fill some of that gap.

We’ve seen that custom properties can be used inside existing color functions like rgb() and hsl() but they can also be used in calc(). This means that we can convert a real number to a percentage by multiplying it, e.g. calc(50 * 1%) = 50%.

:root 
  --lightness: 50;

body 
  background: hsl(25, 80%, calc(var(--lightness) * 1%));

The reason we want to store the lightness value as a real number is so that we can manipulate it with calc before converting it to a percentage. For example, if I want to darken a color by 20%, I can multiply its lightness by 0.8. We can make this a little easier to read by separating the lightness calculation into a locally scoped custom property:

:root 
  --lightness: 50;

body 
  --lightness: calc(var(--lightness * 0.8));
  background: hsl(25, 80%, calc(var(--lightness) * 1%));

We could even abstract away more of the calculations and create something like color modification function in CSS using custom properties. This example is likely too complex for most practical cases of theming, but it demonstrates the full power of dynamic custom properties.

Simplify Theming

One of the advantages of using custom properties is the ability to simplify theming. The application doesn’t need to be aware of how custom properties are used. Instead, we use JavaScript or server-side code to set the value of custom properties. How these values are used is determined by the stylesheets.

This means once again that we are able to separate logic from design. If you have a technical design team, authors can update stylesheets and decide how to apply custom properties without changing a single line of JavaScript or backend code.

Custom properties also allow as to move some of the complexity of theming into the CSS and this complexity can have a negative impact on the maintainability of your CSS, so remember to keep it simple wherever possible.

Using Custom Properties Today

Even if you’re supporting IE10 and 11, you can start using custom properties today. Most of the examples in this article have to do with how we write and structure CSS. The benefits are significant in terms of maintainability, however, most of the examples only reduce what could otherwise be done with more complex code.

I use a tool called postcss-css-variables to convert most of the features of custom properties into a static representation of the same code. Other similar tools ignore custom properties inside media queries or complex selectors treating custom properties much like preprocessor variables.

What these tools cannot do is emulate the runtime features of custom properties. This means no dynamic features like theming or changing properties with JavaScript. This might be OK in many situations. Depending on the situation, UI customization might be considered a progressive enhancement and the default theme could be perfectly acceptable for older browsers.

Loading The Correct Stylesheet

There are many ways you can use postCSS. I use a gulp process to compile separate stylesheets for newer and older browsers. A simplified version of my gulp task looks like this:

import gulp from "gulp";
import sass from "gulp-sass";
import postcss from "gulp-postcss";
import rename from "gulp-rename";
import cssvariables from "postcss-css-variables";
import autoprefixer from "autoprefixer";
import cssnano from "cssnano";

gulp.task("css-no-vars", () =>
  gulp
    .src("./src/css/*.scss")
    .pipe(sass().on("error", sass.logError))
    .pipe(postcss([cssvariables(), cssnano()]))
    .pipe(rename( extname: ".no-vars.css" ))
    .pipe(gulp.dest("./dist/css"))
);

gulp.task("css", () =>
  gulp
    .src("./src/css/*.scss")
    .pipe(sass().on("error", sass.logError))
    .pipe(postcss([cssnano()]))
    .pipe(rename( extname: ".css" ))
    .pipe(gulp.dest("./dist/css"))
);

This results in two CSS files: a regular one with custom properties (styles.css) and one for older browsers (styles.no-vars.css). I want IE10 and 11 to be served styles.no-vars.css and other browsers to get the regular CSS file.

Normally, I’d advocate using feature queries but IE11 doesn’t support feature queries and we’ve used custom properties so extensively that serving a different stylesheet makes sense in this case.

Intelligently serving a different stylesheet and avoiding a flash of unstyled content is not a simple task. If you don’t need the dynamic features of custom properties, you could consider serving all browser styles.no-vars.css and using custom properties simply as a development tool.

If you want to take full advantage of all the dynamic features of custom properties, I suggest using a critical CSS technique. Following these techniques, the main stylesheet is loaded asynchronously while the critical CSS is rendered inline. Your page header might look something like this:

<head>
  <style> /* inlined critical CSS */ </style>
  <script> loadCSS('non-critical.css'); </script>
</head>

We can extend this to load either styles.css or styles.no-vars.css depending on whether the browser supports custom properties. We can detect support like this:

if ( window.CSS && CSS.supports('color', 'var(--test)') ) 
  loadCSS('styles.css');
 else 
  loadCSS('styles.no-vars.css');

Conclusion

If you’ve been struggling to organize CSS efficiently, have difficulty with responsive components, want to implement client-side theming, or just want to start off on the right foot with custom properties, this guide should tell you everything you need to know.

It comes down to understanding the difference between dynamic and static variables in CSS as well as a few simple rules:

  1. Separate logic from design;
  2. If a CSS property changes, consider using a custom property;
  3. Change the value of custom properties, not which custom property is used;
  4. Global variables are usually static.

If you follow these conventions, you will find that working with custom properties is a whole lot easier than you think. This might even change how you approach CSS in general.

Further Reading

Smashing Editorial
(ra, yk, il)


Link to article – 

A Strategy Guide To CSS Custom Properties

Tips For Conducting Usability Studies With Participants With Disabilities

Over the last few years, I ran several usability studies with participants with various disabilities. I thought it would help others if I shared some of my experiences.

In this article, I provide lessons learned or tips to consider in planning and executing usability testing with participants with disabilities. The lessons learned are divided into general that can apply to all types of disabilities; and lessons learned for three specific disability categories: visual, motor, and cognitive. These tips will help you regardless where you work: If you work with an established user research team where usability testing is part of your design process or if you work on your own with limited resources but want to improve the quality of the user research by expanding the diversity of participants.


Windows 10 high contrast mode of Google.com


Windows 10 high contrast mode of Google.com. (Large preview)

Background

Several of our clients from a state government agency to several fortune 500 companies came to us at the User Experience Center (UXC) for help with their websites. They wanted to make sure users with disabilities could access their site and accomplish their goals.

There are many different kinds of disabilities, however, there is a general agreement to categorize people with disability into four general categories: visual, auditory, motor (also referred to as “physical”), and cognitive. There are different conditions and much variability within each category, e.g., within visual disabilities, color blindness, low vision, and blindness. There is also a distinction as to when a disability is contracted, e.g., a person who was born blind as opposed to one who lost vision later on in life.

Furthermore, as we age or encounter unique situations (such as multi-tasking), we may have a similar experience to people we think of as disabled. Therefore, disabilities should be thought of as a spectrum of abilities that should be accounted for during the design of all user interfaces and experiences.

Typically, in order to ensure that disabled people can use their digital products and services, companies aim for compliance with accessibility guidelines such as the Web Content Accessibility Guidelines (WCAG 2.0). While this is critical, it is also important to have users with disabilities try to accomplish real tasks on the site in usability testing. There may be gaps in the overall user experience…

Think about the typical doors found in buildings. How many times have you tried to open a door one way and realized they actually open the other, for example, push instead of pull. Technically the door is accessible, but it is usable?


Example of doors that are technically accessible, but not usable


Example of doors that are technically accessible, but not usable (handles give impression you should push but must pull to open). (Large preview)

Even if a site follows the accessibility guidelines and is technically accessible, users may not be able to accomplish their goals on the site.

Lesson Learned

In most ways, usability testing with this segment of the population is no different than testing with anyone else. However, there are several areas you need to pay just a bit more attention to so your sessions run smoothly. The lessons or tips are broken down into general ones that can apply to all participants and specific tips for various disability types such as visual, motor, and cognitive.

General Lessons Learned

1. Ensure a baseline level of accessibility before usability testing

Ensure a baseline level of accessibility before usability testing: Planning usability testing, especially recruiting participants can take time both for the project team and the recruited participants.

Two good examples of basic accessibility issues that should be addressed prior to usability testing are:

  • Missing alternative (alt) text.
    Usability testing can be used to see if the alt text used is appropriate and makes sense to participants, but if all the participants are doing is confirming that the alt text is missing then this is not a good use of their time.
  • Appropriate color contrast.
    All page designs should be reviewed beforehand to make sure all foreground and background colors meet WCAG 2.0 AA color contrast ratios.
2. Focus the recruiting strategy

If you work with an external recruiter ask them if they have experience recruiting people with disabilities; some do. If you are recruiting internally (without an external recruiter), you may need to reach out to organizations that have access to people with disabilities. For example, if you need to recruit participants with visually disabilities in the United States, you should contact a local chapter of the National Federation of the Blind (https://nfb.org/state-and-local-organizations) or a local training center such as the Carroll Center for the Blind in Massachusetts (http://carroll.org/). If you use social media to advertise your study, a good approach is to use the hashtag #a11y (stands for accessibility — there are 11 letters between the “a” and “y”) in your post.

3. Bring their own equipment/assistive technology

Allow and encourage participants to bring their own equipment such as their own laptop, especially if they use assistive technology. This way, you can truly see how people customize and use assistive technology.

4. Have a backup plan for assistive technology

As stated above in #3. It is best if participants can bring their own equipment. However, it is always wise to plan for the worst, for example, if a participant does not bring their equipment or if there is a technical problem such as you can’t connect their equipment to your Wi-Fi network. In the case of visually impaired participants, install assistive technology (AT) such as screen reader software they will be bringing in on a backup PC. For many of the AT software packages, you can get a free trail that should cover you for the usability testing period. This has saved us several times. Even though the configuration was different than what the participants had, we were able to run the session. Participants were quickly able to go into the settings and make some adjustments (e.g., increase the speech rate) and get started with the session.

5. Allow additional time

Provide additional time in-between sessions. Typically we like to reserve 30 minutes between participants. However, when participants plan to bring in their own equipment additional time may be required for setting up and resolving any issues that may arise. When testing with individuals with disabilities, we schedule an hour between sessions, so we have extra time for setting up assistive technology and testing it.

6. Confirm participant needs

Either with the recruiting screener or via email or telephone, confirm what equipment participants will bring in and need to be supplied beforehand. In our lab, we can connect external laptops (that in this case, were outfitted with special accessibility software and settings) to our 1Beyond system via an HDMI cable. In a recent study, all of our participants’ laptops had HDMI ports. However, we forgot to check this beforehand. This is an example of a small but important thing to check to prevent show-stopping issues at the time of the test.

7. Consider additional cost

Depending on the disability type transportation to the usability testing location may add additional burden or cost. Consider the cost of transportation in the incentive amount. If feasible, consider providing an extra $25-$40 in your incentive amount so participants can take a taxi/Uber/Lyft, etc. to and from your location. Depending on access to public transportation and taxi/ride-sharing rates in your area the amount may vary. Our participants came to the UXC in different ways — some more reliable and timely than others.

8. Revise directions

Check the directions you provide for accessibility. Make sure they include an accessible path into your building. Test them out beforehand. Do you need to provide additional signage? If so, ensure all signs are clear, concise, and use plain-language directions.

9. Review the emergency evacuation plan

Review the plan in the event of a fire or other emergency. Map out the emergency evacuation plan in advance.

10. Consider logistics

Consider remote usability testing as an option. One of the benefits of bringing individuals with disabilities into the lab for usability testing is observing first-hand participants’ use of the product or website in question. However, the logistics of getting to your location may be just too much for participants. If it’s possible to test remotely (we typically do this through Zoom or GoToMeeting), it should be considered. This poses the additional challenge of making sure your process for capturing the remote session is compatible with all of the participant’s assistive technology, as well as accessible itself. Troubleshooting remotely is never fun and could be more difficult with this segment of the population.

11. Hearing impaired participants

Some participants may have a hearing impairment where the position of the moderator and participant is critical for adequate communication. In the case of hearing-impaired participants, it is important to get their attention before talking to them and also to take turns when engaging in conversation.

To get the most of this research, it is best if the participants are not discovering basic accessibility issues that should have been discovered during an accessibility review and/or testing.

Lessons Learned For Participants With Visual Disabilities

Participants with visual disabilities range from people who are blind and use screen readers such as JAWS, to people that need to the text or the screen to be enlarged using software such as ZoomText or relying on the native screen enlargement in the browser. People that are color-blind also fall into this category.

  • For any documents needed prior to the study such as the consent form, send via email beforehand and ask them review and send back in lieu of a physical signature. If you don’t, be prepared to read aloud the consent form and assist in signing the documents for some participants.
  • Make sure directions provide step-wise directions; do not rely only on graphical maps as these may not be accessible.
  • For all documents, make sure color is not used as the sole cue to convey information. Print out all documents on a black and white printer to make sure color is not required to make sense of the information.
  • Get participants mobile phone numbers in advance and meet them at their drop-off point. Be prepared to guide them to the testing location. Review best practice for guiding blind individuals:
  • While Braille documents can be helpful for participants that read Braille, the time and cost involved may not be feasible. Furthermore, all blind people do not read Braille, especially people that have lost sight later in life. It is best to make sure all documents can be read via a screen reader. Unless you are sure if there are no accessibility issues avoid PDF documents and send out simple Word documents or text-based emails.
  • If participants bring guide dogs do not treat them as pets, they are working. Provide space for the dog and do not pet it unless the participant gives you permission.
  • Make sure to explain beforehand any sounds or noise that are or may be present in the room such as unique audio from recording software. This may avoid the participant from becoming startled or confused during the session.
  • Initially when I started to work with blind participants I was worried my choice in language might offend. However, over the years I have learned that most blind participants are fairly relaxed when it comes to speech. Therefore, during moderation do not be afraid to use phrases such as “see” or “look” and similar words when talking to blind participants; for example, “please take a look at the bottom of the page” or “what do you see in the navigation menu?” In my experience, blind participants will not be offended and will understand the figurative meaning rather than the literal meaning.
  • Test out all recording equipment/processes beforehand. Ensure all audio including both human speech in the room and audio/speech from AT such as screen readers will be recorded correctly. During testing of the equipment adjust the locations of the microphones for optimal recording.

Lessons Learned For Participants With Motor Disabilities

Motor disabilities refer to disabilities that affect the use of arms or legs and mobility. These individuals may need to use a wheelchair. Some people may not have full use of their hands or arms and cannot use a standard mouse and keyboard. These people may need to voice recognition software which allows to use voice input or use a special pointing device, for example, one that is controlled by their mouth.

  • In the directions, make sure the route is accessible and routes them via elevators rather than stairs. Also, if participants are driving note the location of accessible parking.
  • Note if doors have accessible door controls. If not you may need to meet the participant and guide them to the testing location.
  • Make a note of the nearest accessible restrooms to the testing location.
  • As with all participants with disabilities, it is best if they can bring in their own laptop with their assistive technology software installed and any other required assistive technology. However, in the case of participants (such as Adriana in Figure 3) that use voice recognition software such as Dragon Naturally Speaking this is critical because they have trained the software to recognize their voice.
  • Make sure the desk or table where the participant will be working can accommodate a wheelchair and the height is adjustable. According to the American with Disabilities Act (ADA), conference tables must be 27 inches high in order to accommodate knee clearance for individuals in wheelchairs..

Adriana Mallozzi conducting a usability test at the User Experience Center. Picture-in-Picture view of the computer page taking up most of the screen and small video feed of Adriana n the lower right-hand corner


Adriana Mallozzi conducting a usability test at the User Experience Center. Adriana has a motor disability (cerebral palsy) which affects her entire body. She uses a wheelchair, a sip-and-puff joystick that acts as a mouse, along with Dragon Naturally Speaking. (Large preview)

Lessons Learned For Participants With Cognitive Disabilities

Individuals with these disabilities cover a wide range of relatively mild learning disabilities such as Dyslexia to individuals with a more profound cognitive disability such as Down syndrome. In general, people with cognitive disabilities have challenges with one or more mental tasks. Rather than looking at specific clinical definitions it best to consider functional limitations in key areas such as memory, problem-solving, attention, reading or verbal compensation. Consider how best to accommodate participants during usability testing. Many of the tips below should also apply to all participants, however for this group you need to be extra aware.

  • Sometimes participants will be accompanied by a caretaker or an aide. This person may assist with transportation or may need to be present with the participant during the usability test. If the caretaker is present during the usability test, make sure they understand the structure of the usability test and what will be required of the participant. If you know the participant will be accompanied before the study, you review the goals and protocol prior to arrival via email or phone. That is as much as possible the participant should be one conducting the usability testing, and the caretaker should not be involved unless it is completely necessary.
  • In some cases, the caretaker or aide may act like an interpreter. You may need to communicate with this interpreter in order to communicate with the participant. If this is the case, make sure you record the audio coming from both the participant and the interpreter.
  • Provide instructions in multiple modalities, for example, both written and verbal. Be patient and be prepared to repeat the task or ask the same question multiple times.
  • Be prepared to break tasks into smaller sub-tasks to support memory/attention challenges or fatigue that may set in.
  • Ideally, it is best to be consistent with tasks for all participants however for some participants with cognitive disabilities you should be prepared to go off-script or modify tasks on the fly if the current approach is not working.
  • Have the participant’s comfort and well-being the number one priority at all times. Don’t be afraid to take multiple breaks or end the session early if things are just not working out or the participant is not comfortable.



Amazon.com home page zoomed in at 250%. (Large preview)

Additional Insights

The tips above should serve as guidelines. Each participant is unique and may require various accommodations depending on their situation. Furthermore, while some of the tips are categorized for specific disability types, specific individuals may have multiple disabilities and/or benefit from a tip from a different category than their primary disability.

If you or your company have conducted user or customer research, you know the value of gathering feedback about the issues and benefits of products and systems. Testing with individuals with disabilities is no different, as you learn many insights that you would not gain otherwise. However, an additional takeaway for us was the realization that people use assistive technologies in different ways. The following example is specific to people with visual disabilities, but there are similar examples across all groups.

An assumption might be someone that is blind only uses a screen reader such as JAWS and is an expert at it. We found that people with visual impairments actually differ greatly in the level of support needed from assistive technology.

  • Some users need a screen reader for accessing all content.
  • Some users (with more sight/with low vision) only need to enlarge content or invert page colors to increase contrast.
  • Others may need a combination of approaches. One visually impaired participant used both a screen reader along with the zoom function embedded in the web browser. She only used a screen reader for large paragraphs of text, but otherwise simply zoomed in with the web browser and got very close to the screen when navigating around the website.

Furthermore, just like anyone, all users are not experts on the software they use. While some users would consider themselves experts, some only learn enough about the software to accomplish what they need and no more.

Moving Forward

Hopefully you have learned some useful information that will help you include more diversity into your usability testing. However, since there is variability with different disabilities, this may seem overwhelming. I recommend starting small; for example by including one or two participants with disabilities as part of a larger group of 5 to 10 participants. In addition, initially bring in someone that has both experience with usability testing and a lot of experience with their assistive technology so you can focus on getting their feedback rather than how the usability testing process works or their use of their assistive technology.

Acknowledgements

I would like to thank Jocelyn Bellas, UX Researcher at Bank of America and Rachel Graham, UX Researcher at Amazon. When Rachel and Jocelyn worked at the User Experience Center as Research Associates in 2016, they worked with me on some of the projects referenced in this article and also contributed to a related blog post on this topic.

References

Smashing Editorial
(cc, ra, yk, il)

View this article: 

Tips For Conducting Usability Studies With Participants With Disabilities

A Simple Guide to Understanding and Creating a Website Conversion Funnel

How many articles have you read recently about the “conversion funnel”? Probably a lot. If you regularly read marketing blogs, it can sometimes feel like you’re hearing, seeing, and having the term “conversion funnel” shoved in front of your eyeballs constantly. I personally come across conversion funnel information multiple times per day when I’m focused on research and reading. It seems like every marketer in existence wants to be sure I don’t forget about this part of my strategy. So why is this? The short is answer is that an optimized conversion funnel is critical to your online marketing success. You might be…

The post A Simple Guide to Understanding and Creating a Website Conversion Funnel appeared first on The Daily Egg.

See original article: 

A Simple Guide to Understanding and Creating a Website Conversion Funnel

9 Ways to Use Heatmaps to Improve Your SEO

using heatmaps to improve seo

Using heatmaps is like being Jason Bourne. You get to spy on your visitors and see exactly what they’re doing. And, like Jason Bourne, you’re not trying to be evil — you’re just trying to understand what they want. The same is true with SEO. You’re trying to understand what keywords people are searching for to find your business. You need to know what content you can create to drive links and keyword rankings. Essentially, the idea behind both is that the better you understand your audience, the better you’ll be at creating content that meets their needs. And when…

The post 9 Ways to Use Heatmaps to Improve Your SEO appeared first on The Daily Egg.

Visit site: 

9 Ways to Use Heatmaps to Improve Your SEO

A Comprehensive Guide To UI Design

(This is a sponsored article.) With the big picture established — mapping user journeys and defining your design’s look and feel — my fifth article in this series of ten articles dives into the details of designing user interface components.
UX, IA, UI: All of these abbreviations can be confusing. In reality, as designers, we’ll often be working across these different specialisms: designing the overall user experience (UX), organizing information logically as we consider information architecture (IA), and considering the granular design of the user interface (UI).

Source: 

A Comprehensive Guide To UI Design

Product Awareness Month: Why I’m Writing 30 Blog Posts in 30 Days

alt : https://unbounce.com/photos/30-in-30.mp4https://unbounce.com/photos/30-in-30.mp4

We Have 1.06 Products.

I wrote that statement on a whiteboard at the start of a website brainstorm session.

What does 1.06 products mean?

1.06 sums up my frustration at the adoption rate of our new products. Yup, Unbounce is now more than just a landing page builder. We released two new products, namely “overlays” and “sticky bars”, and we grouped them together under an umbrella term “Convertables”.

The number 1 represents our flagship industry-leading landing page product (100% of our customers have adopted it), and the .06 represents the tragic adoption rate of our new products (6%).

And yes, you’d be correct if you noted that “Convertables” isn’t a real word, but then neither is Unbounce, so we went with it after a notable amount of company-wide polling, and general corporate groupthink. More on that later.

So, how does this scenario result in me writing 30 blog posts about our products?

Rewind to October 5th: I was in a meeting with fellow co-founders Rick, Carl, and Carter, openly expressing my frustration with the adoption numbers, and Carter interrupted me to ask, “Okay, fine, but what are you going to do about it?”.

Then this video happened…

Awesome, right?! Yeah, it is, until the moment I realized it’s been exactly 301 days since I last wrote a blog post (I’ve been focusing on public speaking), making this level of bravado a tad audacious at best. Aaand, yes I realize I was a little intoxicated in the video.

But, I’ve learned over the years, that being a bit ridiculous in my promises is the only way I really know how to get shit done. When I tell everyone that I’m doing something big, the self-imposed peer pressure is what motivates me to make sure I complete my mission.

Enter Product Awareness Month (PAM)

This brings me to our blog. We’ve never written much about our products on the blog, in fact, we’ve actively avoided it to let the content speak for itself as an educational pillar of the community, and to remain non-salesy.

I’ve realized though, that it doesn’t make much business sense to be that overtly humble in all marketing communications. There has to be a way to balance exposing people to your product without it detracting from the experience.

It’s my fault in many ways. When I started our blog back in 2009, I had a mission to be different from our competitors, to not come across as a salesperson, and just to provide value and entertaining content that stood out.

We dominated the realm of conversion content for many years, but in an increasingly competitive SaaS martech space, our content is no longer number one, and it’s time that we change our approach.

Which is why we’re doing a blog takeover for the whole of January.

Our goal is to explore a blog topic we’ve not covered before, but also to expose a transparent window – transparency is one of our six core values at Unbounce – into our journey as a company, as a marketing team, and myself personally, to become better at marketing our new products.

For me, it’s the first time I’ve ever been involved in product marketing, which will make it a fascinating personal journey reinventing myself as a different kind of marketer.

I’m also cutting the number of speaking gigs I do in 2018 in half, because let’s be honest, in this moment, the success of Unbounce can be more rapidly impacted by me staying home than being on the road.

Transparency

Along the way, I’ll be opening up the Unbounce vault to share our core metrics with you. This will include our churn and product adoption metrics, which we hope to be able to lift in a big way throughout this 30-day experiment. There will be data check-ins throughout, with a halfway report, and then a full “Results Show” at the end.

I’ll also be digging into our analytics to see what the engagement and attribution looks like for every one of the 30 blog posts.

Some of the content will revolve around the learnings and experiences of becoming a better product marketer, and the rest will be an exploration of the ways we’re trying to rethink what our products are, what they mean to our customers, and how we can do a better job communicating their benefits (with some case studies and new ways of thinking – I hope).

I say “I hope” because I’m writing this as you read it. That’s what tends to happen when you commit to something as absurd as 30-in-30.

Follow Along << Mid-Post CTA

I encourage you to follow along by subscribing to our weekly update emails at the bottom of the page. I’m really keen to have our community (that’s you) help us explore how to do this properly, and hopefully, we’ll all learn how to do a better job of marketing our products.

This is a screenshot of the subscribe form at the bottom of the post. Thought you should know.

You can also subscribe by clicking here to launch a popup (using the on-click trigger feature) which contains the subscribe form. << product marketing much?

Aaand I’ve configured it so you’ll see an exit popup when you leave this page. Note, that I’m doing this to show the product in a relevant and hopefully useful manner.

Unbounce Product Adoption Metrics

How do we measure adoption at Unbounce? To understand, it helps to explain a little about how we define a customer. In the old days, a customer was any signup, someone who started a 30-day trial. Over time we learned we should be measuring a little deeper into the customer lifecycle, and decided a customer was someone who paid us twice; once after the 30-day trial, and again after sixty days.

In 2017 we modified this further to someone who pays us three times, giving us a much better sense of true churn numbers.

To be considered a customer who has adopted our products, we have an additional set of app usage criteria:

For landing pages adoption means: a customer who has built and published one or more pages, has set up a custom domain, configured an integration with another tool, and has paid us three times.

For “Convertables” (Overlays & Sticky Bars) adoption means: a customer who has built and published a popup or sticky bar, installed our one-line global Javascript on their website, received at least 10 conversions, and has paid us three times.

Full transparency: 6% adoption for a new product sucks.

So what went wrong? Why was adoption so low?

Well, first, and most importantly, product marketing is really hard.

We also made a few (well intended) mistakes, namely…

Mistake #1: We called a popup an overlay.
Mistake #2: We created a fictitious umbrella term “Convertables” for only two child products, and for a few months, only one child product.
Mistake #3: We assumed that people would find and use these two products, hidden behind said umbrella term in the app.
Mistake #4: We assumed that the functional user of our landing page product would be the same person who needs to use popups and sticky bars.

How do we un-f*** this problem?

The first thing we’re doing is removing public-facing mentions of the term “Convertables”. This has excited the marketing team because it’s much easier to market something when you know how to describe it, and a multi-product value prop is much harder than a single-product value prop.

Beyond that, the approach I’m taking is a combination of four primary tenets:

  1. First, is a concept I call “Productizing Our Technology” or POT for short. This is about discovering new and novel ways that our platform can be used, that people either haven’t imagined or simply didn’t know was possible.
  2. Second, is exploring the entire Unbounce ecosystem, from the app, to the website, our content channels, and our community, to see how we could do a better job of exposing the benefits of our products to those who can benefit from them.
  3. Third, is using the Product Awareness Month blog takeover to create interactive demonstrations right here on the blog – the goal of which is to reduce the Time to Value (TTV) by creating more obvious ah-ha moments.
  4. Fourth, understanding who the various target personas and functional users of the different products are, and adjusting our targeting and marketing communications to find and speak to those potentially different users.

In regards to #3 the blog takeover, if you take a look at the top of the screen, you’ll see a header bar like this:

Or this one, if you have scrolled down the page:

If you look at the hierarchy of information from left to right, you see: 1) Who we are: logo, 2) What we do: value prop, 3) How to take action: the three big orange buttons.

This is hugely different to the rest of the blog, which retains the navigation of the whole site (I’ve thought that was incongruent for a long time).

My hope is that the new header bar helps more people know what we do, and how our products can help. I’ll be tracking engagement with the 3 CTAs and comparing these 30 posts against our other blog content in terms of its ability to get people to sign up.

Productizing Our Technology: Landing Pages, Popups, & Sticky Bars

I had my own ah-ha moment when I started imagining all the ways that I could hack/modify/extend the ways the Unbounce conversion platform can be used. We have 3 core pieces of product technology (not including our AI/Machine Learning efforts that will power our technology in the future): landing pages, popups, and sticky bars.

By taking our core tech, combining the available features, with new jQuery scripts, CSS, and some 3rd-party integrations, it’s possible to create a plethora of new “mini-products” that if embraced by the community, might inform future product direction.

Take a look at the spreadsheet below. This is my POT matrix. The complete sheet currently houses over 120 new product ideas.

Productizing Unbounce Technology
(Click image for full-size view)

Across the top (in yellow) are the core products, their features (such as targeting, triggers, display frequency), and the different hacks, data sources, and integrations, that can be combined to produce the new products listed in green in the first column.

Each product is flagged as being in one of three states:

NOW: These products are possible now with our existing feature set.
MVP: These products are possible by adding some simple scripts/CSS to extend the core.
NEW: These products would require a much deeper level of product or website development to make them possible. These are the examples that came from “blue sky” ideation, and are a useful upper anchor for what could be done.

I’ll be explaining these use cases in greater detail as the month progresses, and I’ll be building some of them directly into these blog posts as I write them. << FTR this will involve me reverting to my long-extinct coding background to hack the shit out of the blog to show you what I’m talking about.

Please Follow Along

That’s the intro, that’s what happened, and what we’re going to do to try and fix it. Subscribe to the weekly email updates, join the discussion in the comments, and chat directly with me on Twitter.

There is also a calendar at the bottom of every post that will link to all 30 PMM topics as they roll out.

What’s coming on day 2 of PMM?

Tomorrow’s post is called “50 Creative Ideas Your Marketing Team Can Use to Improve SaaS Product Adoption & Awareness”. It’s based on the results of rapid-fire brainstorms which exposed quick-win tactics all product marketers can use to expose your products in small and simple ways, to build to a critical mass of awareness.

This should be very relevant to anyone in marketing, and doubly so to those working for a SaaS business.

Here’s to kicking off 2018 in a blaze of product marketing glory.

Cheers,
Oli Gardner

p.s. Please jump into the comments below to let me know what products you’re currently trying to take to market.

Original article: 

Product Awareness Month: Why I’m Writing 30 Blog Posts in 30 Days

Designing For A Browserless Web

What happens when we take the web browser out of web browsing? Google’s new “Add to Homescreen” feature delivers fast, focused web experiences that are indistinguishable from those of a native app. What can designers learn from the successes of early adopters such as Twitter, and how can we leverage app-like design patterns to tackle this brand new set of user experience challenges?
The “Add to Homescreen” installation process, as shown on Google Chrome Developer’s mobile website (Image source) (Large preview) We’ve seen debates on the topic of native versus web experiences.

Visit site – 

Designing For A Browserless Web

Using CSS Grid: Supporting Browsers Without Grid

When using any new CSS, the question of browser support has to be addressed. This is even more of a consideration when new CSS is used for layout as with Flexbox and CSS Grid, rather than things we might consider an enhancement.
In this article, I explore approaches to dealing with browser support today. What are the practical things we can do to allow us to use new CSS now and still give a great experience to the browsers that don’t support it?

Excerpt from:

Using CSS Grid: Supporting Browsers Without Grid

Launching Your Design Career: Which Type Of Education Is Best For You?

If you’re stuck in a job you hate and have dreams of becoming a designer and working in a creative role that fills you with excitement daily, the road to entering this completely new industry can feel daunting. Making a major career shift late in life to follow your passion is scary. Not only is it sometimes difficult to know where to start to learn about an expansive field like design, but it can also feel risky, especially if you’re working a secure job.

Link: 

Launching Your Design Career: Which Type Of Education Is Best For You?

Intrusive Interstitials: Guidelines To Avoiding Google’s Penalty

In 2015, Google announced that mobile searches surpassed desktop searches in at least 10 countries. 56% of traffic on major websites comes from mobile. In light of this, Google’s decision to improve the mobile user experience by various means, such as AMP pages and a dedicated mobile index, comes across as a sound business move.
More than half of the 2 trillion searches Google processes each year come from mobile devices.

Source article – 

Intrusive Interstitials: Guidelines To Avoiding Google’s Penalty

Just another WordPress site