Tag Archives: using

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

A Blueprint for the Perfect Popup: Structured Design for Unstructured Marketers

Is it possible to design the perfect popup? One so fiercely potent that people just can’t refuse to convert?

Of course not.

As small as seemingly simple as a popup is, it’s still important to understand a little about its anatomy. There are five primary elements to make up the architecture of a popup, and then there’s a layer of interaction design beneath that which deals with the functional aspects such as triggers and targeting.

The five primary elements of a popup blueprint are:

  1. Headline and subhead
  2. Offer details
  3. Hero images
  4. Trust and social proof
  5. Call to Action

Using a structural approach to your popup designs helps us avoid mistakes and choose the right interaction modes and content elements that will create a good conversion experience.

Obviously, you can’t use every version of every element on a single small popup, but you can choose the best parts of each anatomical section to craft something that presents your offer in the best possible way.

An important thing to know is that the circled icons beneath each section represent Unbounce functionality that allows you to make your popups way more awesome than they would be if you simply showed it to everyone.

Got any weird and wonderful popup designs?

If you have designs that include elements I didn’t include in the blueprint, share them in the comments so I can add them to my layout specs.

Popups that don’t suck, rule! Make better popups, please.

Cheers,
Oli

p.s. See what Unbounce Popups look like on your website with the new Live Preview Tool. It’s really cool.

p.p.s. Don’t forget to subscribe to the weekly updates for the rest of Product Awareness Month. If you click that link a popup will appear!

Read more:

A Blueprint for the Perfect Popup: Structured Design for Unstructured Marketers

Thumbnail

Using Latent Semantic Indexing to Improve Your SEO Ranking and Boost Organic Traffic

latent semantic indexing SEO

When was the last time you sat down to write an amazing piece of content, pulled out your mathematical matrix for determining the most valuable keyword phrases, and set to work with a smile on your face? Yeah, me neither. If SEO and content marketers were forced to use a mathematical model to discover valuable keywords, our jobs would be a hundred times harder than they are now. Thankfully, there’s a little thing called latent semantic indexing (LSI) which can take your SEO ranking game from “0” to “100” in a jiffy (more like “100” to “1” if we’re getting…

The post Using Latent Semantic Indexing to Improve Your SEO Ranking and Boost Organic Traffic appeared first on The Daily Egg.

Continue reading:  

Using Latent Semantic Indexing to Improve Your SEO Ranking and Boost Organic Traffic

Taming Advanced Color Palettes In Photoshop, Sketch And Affinity Designer

Creating large, harmonious and uniform color palettes can be a challenge. Good intentions and confident plans can be abandoned when things get a little unwieldy. But you can equip yourself with some tools to manage the complexity. With the right techniques, large color palettes can be created, refined and refactored at will. Large color palettes can be tamed.
Creating Color Palettes Using Adjustment Layers Quite a few techniques can be used to create large color palettes from a few base colors.

See the article here: 

Taming Advanced Color Palettes In Photoshop, Sketch And Affinity Designer

Glossary: Multivariate Testing

Multivariate Testing

A type of hypothesis testing where multiple variables are tested simultaneously to determine how the variables and combinations of variables influence the output. If several different variables (factors) are believed to influence the results or output of a test, multivariate testing can be used to test all of these factors at once.  Using an organized matrix which includes each potential combination of factors, the effects of each factor on the result can be determined. Also known as Design of Experiments (DOE), the first multivariate testing was performed in 1754 by Scottish physician James Lind as a means of identifying (or…

The post Glossary: Multivariate Testing appeared first on The Daily Egg.

Original article:

Glossary: Multivariate Testing

3 Smart Moves for eCommerce to Fuel Customer Engagement

It is not enough for eCommerce establishments to provide exceptional one-off experiences to their users. eCommerce enterprises have been increasingly working on improving customer engagement with a view to forming long-term and meaningful relationships.

Gallup’s report on customer engagement 2014 states that fully engaged customers represent an average 23% premium in terms of share of profitability, revenue, and relationship growth.

Interestingly, Gallup defines fully engaged customers as those who are both emotionally attached and rationally loyal. To achieve complete engagement, rational loyalty as well as emotional connections need to be leveraged. The influence of social web and its impact on engagement is another aspect toward which eCommerce enterprises need to pay significant attention.

In this blog post, we discuss the three key attributes—emotions, participation, and user behavior—that eCommerce enterprises should focus on to improve customer engagement.

Leveraging Emotions to Drive Engagement

eCommerce enterprises have started paying a lot more attention to whether their customers really associate with the brand and the ways in which they can connect with customers at a deeper emotional level. Dove’s real beauty campaign is a classic example of using emotions to drive engagement. The campaign tapped into the emotions of many women about themselves and their appearance. In their new campaign—#MyBeautyMySay, Dove wants women to define their beauty their own way. Through this campaign, Dove attempts to connect to the self-respect aspect, which many women believe is a “battle still to be won.”

Customer Engagement - Emotional Connection

Targeting Emotions for Customer Engagement

Developing deeper levels of emotional engagement with consumers also requires eCommerce enterprises to foster transparency and trust in customer relationship. Using social proof, trust seals, and reviews on the website creates a sense of trust among their users.

Using humor has a strong emotional appeal, and when used appropriately, never fails to make an impact. For example, Hublogix includes Betabrand in its list of eCommerce excellent marketing for humorous product descriptions on its website.

Using Humor for Customer Engagement
The question, however, is that how do you use customer emotions to take a preferred course of action? A post published on My Customer gives a five-point list on building emotional engagement. The post talks about the following list:

  1. Know what emotional triggers exist currently in your experience.
  2. Define what emotion you want your experience to evoke.
  3. Listen to your customers…a lot.
  4. Identify your customers’ subconscious experiences.
  5. Never stop improving the experience.

Improving Engagement through Participation

Another way to improve user engagement is by soliciting participation. Involve your buyers in product creation and innovation. Consider the example of Vans. The leading shoe brand encourages users to design their own pair of sneakers, using a customization feature.

User Participation for Customer Enagement

Moreover, to increase the engagement level of people who understand the nitty-gritty of the products, eCommerce enterprises can focus on co-creation. McKinsey talks about what brands who have mastered co-creation do to gain an edge over others. They researched more than 300 companies in three European countries and identified three key areas where those who lead at co-creation focused: targeting co-creators, finding the motivation, and focusing on a sustainable pay-off.

Leveraging social media for participation is another way through which eCommerce enterprises can drive more engagement and purchases. According to a 2016 Yotpo consumer survey, 72% of customers say that seeing Instagram photos of a product increases customers’ chances of buying. These numbers give eCommerce enterprises a good reason to invest in social curation for driving user engagement. One way of doing this is using shoppable images on your site—product page, home page, or a dedicated photo gallery page. ASOS makes a creative and engaging use of Instagram images shared by customers, by running the #AsSeenOnMe campaign on its website.

ASOS Customer Engagement with UGC

Warby Parker’s started its home try-on services in 2012. It was also smart of them to start a user-generated content (UGC) campaign for the same. Warby’s customers become a part of the campaign by sharing their photographs while trying the five pairs of Warby glasses and sharing it on their social media with the hashtag #WarbyHomeTryOn.

Forever21 has created a single hashtag for all content generated by its users. (The benefit of using just one hashtag is that people associate better with the brand as well as with the hashtag.) Forever21 has the campaign #F21XME featured on its website, which asks participants to upload their favorite F21 outfit on Instagram using the hashtag, and get a chance to be featured.

User Generated Content for Customer Engagement

Twitter Product pages are helping eCommerce enterprises solicit more meaningful engagement through social media. Twitter product pages are tweets that lead to shopping information about an item. A buy button is included for those who wish to buy.

Twitter Customer Engagement

This post on Sprinkler can be your guide to social commerce.

Leveraging User Behavior to Drive Engagement On-Site

We discussed earlier how emotional loyalty and participation can be leveraged to increase engagement. However, it is equally important for eCommerce enterprises to focus on increasing customer engagement from rationally loyal consumers, which can be done by providing them an enhanced on-site experience. Continuously improving users’ on-site experiences requires eCommerce enterprises to dig deep into user insights, identify and resolve pain points, and discover what interests or repels users. This can be done with the help of tools such as heatmaps, visitor recordings, and form analysis.

Visitor recordings play back the actual interactions that any user has had on your website. These insights can be used further to analyze or validate whether any element on the website can prove to be a distraction for the user. In a case study by VWO, about UKToolCenter, removing the product filter improved site engagement by 27%. Using visitor recordings, the hypothesis that the product was a distraction was easily validated.

Heatmaps highlight areas of maximum engagement on a website and also pinpoint dead zones. eCommerce enterprises can study low-engagement areas and suggest actionable improvements, which include:

A form analysis can be run for understanding how users interact with forms. This interaction allows you to fetch insights from drop-offs per field, time taken to fill the form, fields ignored, and so on. This data can be used further for fixing the pain points that users face, and optimize web forms for more engagement and conversions.

Feedback and insights gathered from on-page surveys can also be used for improving on-site user engagement. For example, if a user spends more than five minutes on a product page, a survey can be triggered to find out whether the user intends to buy something or is searching for something specific.

Conclusion

User engagement is not just about metrics that show us click-through rates or pages viewed in a session. For eCommerce enterprises, driving robust engagement constitutes:

  • Leveraging the emotional connection that consumers form with brands
  • Encouraging participation across the website and social channels
  • Deploying user behavior data and insights to track and improve on-site interactions

How are you driving meaningful engagement for your eCommerce enterprise? Drop a comment or feedback below.

cta_fuelCustomerEngagement

The post 3 Smart Moves for eCommerce to Fuel Customer Engagement appeared first on VWO Blog.

Continue reading: 

3 Smart Moves for eCommerce to Fuel Customer Engagement

Using Heuristics to Increase Your Ecommerce Conversion Rate

Every time I hear someone say, “Let’s test if the red button will be better for conversions than green (yellow, blue, etc.)”, my eyes get all bloodshot. I mentally curse whoever it was that wrote the first articles telling you that you can simply test different button colors and get extremely high lifts in conversion. And yet thousands of webmasters and digital marketers spend their time testing button colors. Some of them succeed in making conversions higher, some – not. The problem is, most of them just test color blindly without thinking about why this should work. The funny thing…

The post Using Heuristics to Increase Your Ecommerce Conversion Rate appeared first on The Daily Egg.

Credit: 

Using Heuristics to Increase Your Ecommerce Conversion Rate

Axure 8: A Comprehensive Review

Behind every great invention lie dozens of sacrificed prototypes. It took Michele Ferrero almost five years to perfect the spherical wafer within the famous chocolates that bear his name. No great product or invention emerges fully formed, and this applies to great websites and software as well. Whether you’re working on digital products or chocolates, prototyping plays an important role in any successful project.
If you work in user experience or software development, chances are you will have encountered Axure RP at some point.

Visit source: 

Axure 8: A Comprehensive Review

PostCSS – A Comprehensive Introduction

The development of CSS, like all languages, is an iterative process. With every major release, we get new features and syntaxes that help us write our styles. CSS Level 3 introduced features that enable us to design interactions that previously were possible only with JavaScript. With every new day, tools emerge to make styling easier and more flexible.
One of the relatively recent tools introduced for styling is PostCSS.

See the original article here – 

PostCSS – A Comprehensive Introduction

Guide To Using WebP Images Today (A Case Study)


They say a picture is worth a thousand words. But online, a picture can be worth a thousand kilobytes or more! HTTP Archive shows that images make up 64% of a web page’s total size on average. Given this, image optimization is key, especially considering that many users will abandon a request if it doesn’t load within a few seconds.

WebP Images And Performance

The problem with image optimization is that we want to keep file sizes small without sacrificing quality. Past attempts to create file types that optimize images better than the standard JPEG, PNG and GIF formats have been unsuccessful.

The post Guide To Using WebP Images Today (A Case Study) appeared first on Smashing Magazine.

Link:

Guide To Using WebP Images Today (A Case Study)