Archive

Archive for May, 2020

5 Life Lessons That Apply to Email Marketing

May 11th, 2020 No comments

It can be easy to think of email marketing as this impenetrable thing that only someone with a lot of tech and marketing experience could attempt.

There are good reasons to get involved with email marketing – it’s the best, most personal way to reach people and is a low-cost investment to increase sales. I’m going to break it down for you in a way that will show you that, guess what, a lot of this stuff you already know. You can take on the world of email marketing, learn and have fun while you’re at it.

Your reputation matters

Nobody wants a bad reputation. Conversely, a good reputation can get you a job promotion or a recommendation from a customer. This plays out in the world of email marketing, as well.

Every person who sends emails, whether from a personal or a corporate account, has an email sender reputation. This score helps Internet service providers (ISPs) determine if you are legitimate or not. A good score means it’s highly likely that your email campaigns end up in the inbox. On the other hand, a bad score may cause your emails to land in the spam folder or not even get delivered.

Obviously, you want a solid sender reputation, so how do you build it – or improve it if you’ve tarnished it?

One of the most important things you can do is make sure you use an accurate email list. The thing is even the best of lists will deteriorate over time and therefore need maintenance. A reputable email checker will identify all of those troublesome email addresses (invalid, catch-all, spam traps, role-based, and more) so you can remove them. Every organization needs email list validation. It’s best practices 101.

Know who your friends are

In life, it’s always important to know and remember who your friends are. If people don’t get you or relate to you, letting go of them makes room for those who do.

That applies to your email list, too. You can’t buy friends and you shouldn’t buy an email list either, it should grow organically. Purchasing subscribers is illegal in certain countries. On top of that, it will increase your spam complaints which directly affects your email sender reputation.

Get rid of people who talk badly about you

Some email subscribers are not your friends. In fact, they talk badly about you. In the industry, they’re referred to as malicious or abuse emails. They often mark email newsletters that they signed up for as spam. Sometimes they do it for no reason at all. Other times, they forget they ever subscribed. You don’t want people who call your good, consensual emails spam!

When you get those people off your list you can concentrate on the people who want to be there. And oh, make sure it’s easy for those who don’t want to be on your email list to get off. Have a visible, functioning unsubscribe button. They can see themselves out.

Be consistent

Consistency is the key to success in just about anything. Whether it’s weight loss and physical fitness or learning a new skill, you have to stay at it. So it goes with email marketing as well.

By sending emails consistently, you’ll develop your own style and a better rapport with your readers. Furthermore, by sending emails around the same time every week (or month), you’re more likely to increase your engagement. Your readers will come to expect your emails because they know when you send it out.

So, try to be as consistent with your email newsletters as you are the other parts of your life. It’s not easy, but it’s worth it. Consistency gets results!

Be of service

In life, those who are of service are valued. Usually a hiring manager is thinking about what someone can do for the company. “Why should we give him/her the position?” If all you did was ask about pay and benefits, it would make them think that you didn’t care about being of service. That’s what it’s really all about, right?

An email newsletter that isn’t of service is like a comedian without jokes. So, give your subscribers something they can use, even if it’s simply entertainment. Also, send information, tips, helpful news so you can compel your readers to open your emails.

It’s not surprising to me how email newsletters or promotions that give away a lot tend to have the most to gain. I remember a biscuit bakery that gave away their biscuit recipe in one of the newsletters. You’d think that wouldn’t be a good idea, but instead, it only makes them seem secure in themselves. Interestingly enough, it makes you like them even more, doesn’t it?

You have to go for it

Just like in life, nobody’s going to do it, but you. It may be intimidating, but many of the biggest lessons in email marketing you’ve already learned by cruising down the highways and backroads we call living. The more authentic you are in your email campaigns, the better they will be. Now go forth and email!


Marketing vector created by stories – www.freepik.com

Categories: Others Tags:

20 Unmissable Websites, May 2020

May 11th, 2020 No comments

The world is a strange place at the moment, but design moves on apace, and sites are still being launched.

Every month we post a roundup of the freshest sites we’ve come across in the previous four weeks. This month we’ve included some exciting portfolio sites, a strong selection of health and beauty sites, and some fabulous new takes on technology. Enjoy!

Lynn Fisher

We love the homepage illustration on Lynn Fisher’s website. It’s pretty cool right? Now try resizing your browser window and see what happens. Hats off to her, it’s not often we find such a knowing, humorous, responsive site.

Sonantic

We’ve seen a few sites in the last few months that have tried to present sound visually. Sonantic does a great job of doing exactly that, with an awesome animated logo, gradients, and random texture.

Zand Harirchi Architects

Based in Tehran, Iran, Zand Harirchi is a modern architecture firm with a confidently modern website to match. We can’t get enough of its thumbnails, which as well as piquing interest, are reminiscent of small windows.

Amino Mason

If you’re designing for a health & beauty product, the obvious route is clean and minimal. Amino Mason has gone the other route, producing a site that screams energy. It’s the epitome of modern Japanese design.

Cone

How many sites have you seen for apps that feature a small demo of the app inside a hastily debranded iPhone window? Now look at how expansive, and how filled with potential Cone feels precisely because it isn’t confined.

Queen Garnet

There are two things that make Queen Garnet stand out in its market. The first thing is the excellent brand typography that is completely different to the usual choice of sans-serif. The second thing is the beautiful product photography.

Mike John Otto

Mike John Otto is a designer, creative director, and artist. His portfolio leans towards high-end sound clients, which helps to explain the hypnotic wave form that fluctuates behind the content of this beautifully designed site.

Ester

We love the hand-drawn quality of the illustrations and animations on Ester’s site. The color scheme feels modern and suitably unisex, and we like the way its portfolio is presented in a straightforward, no-nonsense manner.

Goodfish

Crispy fish skins don’t leap to mind when we’re planning which chips to buy, but that’s what Goodfish is selling. The lettering, artwork, and copy are all enough to make us at least try it. Who knows, perhaps the taste matches the health benefits.

Limnia

Limnia is a making a name for itself in fashion circles for its modular jewellery. Its site does a great job of showcasing its product range with fullscreen video, and we love the way the content is divided up with a strong grid to mimic the product’s modularity.

Outer Reach

Stretching is so important for our physical, and mental health, but so many of us get it wrong, or don’t bother at all. Outer Reach is aiming to change that, and we love the way its hero video rotates through perspectives, as if we were already stretching.

Forward

Forward Journal is an online magazine dedicated to creativity. Unlike most blogs out there, it publishes rarely, and in editions, giving it the feel of a traditional print magazine and heightening the sense of occasion by limiting availability.

Minervo

There’s a distinctly latin feel to the Minervo website from Ecuador. The hot pinks and the sun-blasted desaturation of the color scheme feels suitably South American. We love the cropping on the custom typeface.

Helo

If there’s one thing we hate more than coding for IE, it’s coding for email. Helo is an email testing and debugging tool. Its site is an excellent example of how to do responsive design right.

Midi Fighter

Midi Fighter make a range of physical inputs for DJs and musicians who need reliable, and fun equipment for performing. The colorful site uses subtle illustration to expertly add dynamism to otherwise static product shots.

Future London Academy

There’s a long-standing, and highly respected tradition in this blog series that anyone who makes good use of yellow gets in. Future London Academy certainly does that, but what we really love here is the depth created by the typography.

Abbotsford Convent

Abbotsford Convent is a creative arts venue in Melbourne, Australia, situated in a former convent building. To honor the heritage the shapes employed in the UI blend creative motion, with architectural forms.

Lucky Beard

Lucky Beard has a surprisingly restrained color palette considering its penchant for bold statements. It’s hard to go wrong with animated geometry, and we really like the fact that the navigation has been relocated to the right.

USSR Design Almanac

The Soviet Union was, for a brief period — before Stalin denounced modernism as decadent — the world’s first design super-power. The USSR Design Almanac is a fascinating overview of this extraordinary, and often overlooked history.

East Fork

Okay we admit it, when we first came across East Fork’s website we thought it was about chocolate. Look closer and you’ll see these guys offer some really high-class home products, not least their unique pottery.

Source

Categories: Designing, Others Tags:

Setting TypeScript For Modern React Projects Using Webpack And Babel

May 11th, 2020 No comments

Setting TypeScript For Modern React Projects Using Webpack And Babel

Setting TypeScript For Modern React Projects Using Webpack And Babel

Blessing Krofegha

2020-05-11T10:30:00+00:002020-05-11T13:37:23+00:00

In this era of software development, JavaScript can be used to develop almost any type of app. However, the fact that JavaScript is dynamically typed could be a concern for most large enterprise companies, because of its loose type-checking feature.

Fortunately, we don’t have to wait until the Ecma Technical Committee 39 introduces a static type system into JavaScript. We can use TypeScript instead.

JavaScript, being dynamically typed, is not aware of the data type of a variable until that variable is instantiated at runtime. Developers who write large software programs might have a tendency to reassign a variable, declared earlier, to a value of a different type, with no warning or issue whatsoever, resulting in bugs often overlooked.

In this tutorial, we will learn what TypeScript is and how to work with it in a React project. By the end, we’ll have built a project consisting of an episode-picker app for the TV show Money Heist, using TypeScript and current React-like hooks (useState, useEffect, useReducer, useContext). With this knowledge, you can go on to experiment with TypeScript in your own projects.

This article isn’t an introduction to TypeScript. Hence, we won’t go through the basic syntax of TypeScript and JavaScript. However, you don’t have to be an expert in any of these languages to follow along, because we’ll try to follow the KISS principle (keep it simple, stupid).

What Is TypeScript?

In 2019, TypeScript was ranked the seventh most-used language and the fifth fastest-growing language on GitHub. But what exactly is TypeScript?

According to the official documentation, TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. It is developed and maintained by Microsoft and the open-source community.

“Superset” in this context means that the language contains all of the features and functionality of JavaScript and then some. TypeScript is a typed scripting language.

It offers developers more control over their code base via its type annotation, classes, and interface, sparing developers from having to manually fix annoying bugs in the console.

TypeScript wasn’t created to alter JavaScript. Instead, it expands on JavaScript with valuable new features. Any program written in plain JavaScript will also run as expected in TypeScript, including cross-platform mobile apps and back ends in Node.js.

This means you can also write React apps in TypeScript, as we will do in this tutorial.

Why TypeScript?

Perhaps, you aren’t convinced of embracing the goodness of TypeScript. Let’s consider a few of its advantages.

Fewer Bugs

We cannot eliminate all bugs in our code, but we can reduce them. TypeScript checks for types at compile-time and throws errors if the variable type changes.

Being able to find these obvious yet frequent errors this early on makes it a lot easier to manage your code with types.

Refactoring Is Easier

You probably often want to refactor quite a lot of things, but because they touch so much other code and many other files, you’re wary of modifying them.

In TypeScript, such things can often be refactored with just a click of the “Rename symbol” command in your integrated development environment (IDE).

Renaming app to expApp (Large preview)

In a dynamically typed language such as JavaScript, the only way to refactor multiple files at the same time is with the traditional “search and replace” function using regular expressions (RegExp).

In a statically typed language such as TypeScript, “search and replace” isn’t needed anymore. With IDE commands such as “Find all occurrences” and “Rename symbol”, you can see all occurrences in the app of the given function, class, or property of an object interface.

TypeScript will help you find all instances of the refactored bit, rename it, and alert you with a compile error in case your code has any type mismatches after the refactoring.

TypeScript has even more advantages than what we’ve covered here.

Disadvantages Of TypeScript

TypeScript is surely not without its disadvantages, even given the promising features highlighted above.

A False Sense Of Security

TypeScript’s type-checking feature often creates a false sense of security among developers. The type checking indeed warns us when something is wrong with our code. However, static types don’t reduce overall bug density.

Therefore, the strength of your program will depend on your usage of TypeScript, because types are written by the developer and not checked at runtime.

If you’re looking to TypeScript to reduce your bugs, please consider test-driven development instead.

Complicated Typing System

The typing system, while a great tool in many regards, can sometimes be a little complicated. This downside stems from it being fully interoperable with JavaScript, which leaves even more room for complication.

However, TypeScript is still JavaScript, so understanding JavaScript is important.

When To Use TypeScript?

I would advise you to use TypeScript in the following cases:

  • If you’re looking to building an application that will be maintained over a long period, then I would strongly recommend starting with TypeScript, because it fosters self-documenting code, thus helping other developers to understand your code easily when they join your code base.
  • If you need to create a library, consider writing it in TypeScript. It will help code editors to suggest the appropriate types to developers who are using your library.

In the last few sections, we have balanced the pros and cons of TypeScript. Let’s move on to the business of the day: setting up TypeScript in a modern React project.

Getting Started

There are several ways to set up TypeScript in a React Project. In this tutorial, we’ll be covering just two.

Method 1: Create React App + TypeScript

About two years ago, the React team released Create React App 2.1, with TypeScript support. So, you might never have to do any heavy lifting to get TypeScript into your project.

Announcement of TypeScript in Create React App (Large preview)

To start a new Create React App project, you can run this…

npx create-react-app my-app --folder-name

… or this:

yarn create react-app my-app --folder-name

To add TypeScript to a Create React App project, first install it and its respective @types:

npm install --save typescript @types/node @types/react @types/react-dom @types/jest

… or:

yarn add typescript @types/node @types/react @types/react-dom @types/jest

Next, rename the files (for example, index.js to index.tsx), and restart your development server!

That was quick, wasn’t it?

Method 2: Set Up TypeScript With Webpack

Webpack is a static module bundler for JavaScript applications. It takes all of the code from your application and makes it usable in a web browser. Modules are reusable chunks of code built from your app’s JavaScript, node_modules, images, and CSS styles, which are packaged to be easily used on your website.

Create A New Project

Let’s start by creating a new directory for our project:

mkdir react-webpack
cd react-webpack

We’ll use npm to initialize our project:

npm init -y

The command above will generate a package.json file with some default values. Let’s also add some dependencies for webpack, TypeScript, and some React-specific modules.

Installing Packages

Lastly, we’d need to install the necessary packages. Open your command-line interface (CLI) and run this:

#Installing devDependencies

npm install --save-dev @types/react @types/react-dom awesome-typescript-loader css-loader html-webpack-plugin mini-css-extract-plugin source-map-loader typescript webpack webpack-cli webpack-dev-server

#installing Dependencies
npm install react react-dom

Let’s also manually add a few different files and folders under our react-webpack folder:

  1. Add webpack.config.js to add webpack-related configurations.
  2. Add tsconfig.json for all of our TypeScript configurations.
  3. Add a new directory, src.
  4. Create a new directory, components, in the src folder.
  5. Finally, add index.html, App.tsx, and index.tsx in the components folder.

Project Structure

Thus, our folder structure will look something like this:

├── package.json
├── package-lock.json
├── tsconfig.json
├── webpack.config.js
├── .gitignore
└── src
    └──components
        ├── App.tsx
        ├── index.tsx
        ├── index.html

Start Adding Some Code

We’ll start with index.html:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>React-Webpack Setup</title>
</head>
<body>
  <div id="output"></div>
</body>
</html>

This will create the HTML, with an empty div with an ID of output.

Let’s add the code to our React component App.tsx:

import * as React from "react";
export interface HelloWorldProps {
  userName: string;
  lang: string;
}
export const App = (props: HelloWorldProps) => (
         <h1>
           Hi {props.userName} from React! Welcome to {props.lang}!
         </h1>
       );

We’ve created an interface object and named it HelloWorldProps, with userName and lang having a string type.

We passed props to our App component and exported it.

Now, let’s update the code in index.tsx:

import * as React from "react";
import * as ReactDOM from "react-dom";
import { App } from "./App";
ReactDOM.render(
  <App userName="Beveloper" lang="TypeScript" />,
  document.getElementById("output")
);

We just imported the App component into index.tsx. When webpack sees any file with the extension .ts or .tsx, it will transpile that file using the awesome-typescript-loader library.

TypeScript Configuration

We’ll then add some configuration to tsconfig.json:

{
  "compilerOptions": {
    "jsx": "react",
    "module": "commonjs",
    "noImplicitAny": true,
    "outDir": "./build/",
    "preserveConstEnums": true,
    "removeComments": true,
    "sourceMap": true,
    "target": "es5"
  },
  "include": [
    "src/components/index.tsx"
  ]
}

Let’s also look at the different options we added to tsconfig.json:

  • compilerOptions
    Represents the different compiler options.
  • jsx:react
    Adds support for JSX in .tsx files.
  • lib
    Adds a list of library files to the compilation (for example, using es2015 allows us to use ECMAScript 6 syntax).
  • module
    Generates module code.
  • noImplicitAny
    Raises errors for declarations with an implied any type.
  • outDir
    Represents the output directory.
  • sourceMap
    Generates a .map file, which can be very useful for debugging the app.
  • target
    Represents the target ECMAScript version to transpile our code down to (we can add a version based on our specific browser requirements).
  • include
    Used to specify the file list to be included.

Webpack Configuration

Let’s add some webpack configuration to webpack.config.js.

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
  entry: "./src/components/index.tsx",
  target: "web",
  mode: "development",
  output: {
    path: path.resolve(__dirname, "build"),
    filename: "bundle.js",
  },
  resolve: {
    extensions: [".js", ".jsx", ".json", ".ts", ".tsx"],
  },
  module: {
    rules: [
      {
        test: /.(ts|tsx)$/,
        loader: "awesome-typescript-loader",
      },
      {
        enforce: "pre",
        test: /.js$/,
        loader: "source-map-loader",
      },
      {
        test: /.css$/,
        loader: "css-loader",
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, "src", "components", "index.html"),
    }),
    new MiniCssExtractPlugin({
      filename: "./src/yourfile.css",
    }),
  ],
};

Let’s look at the different options we’ve added to webpack.config.js:

  • entry
    This specifies the entry point for our app. It may be a single file or an array of files that we want to include in our build.
  • output
    This contains the output configuration. The app looks at this when trying to output bundled code from our project to the disk. The path represents the output directory for code to be outputted to, and the file name represents the file name for the same. It is generally named bundle.js.
  • resolve
    Webpack looks at this attribute to decide whether to bundle or skip the file. Thus, in our project, webpack will consider files with the extensions .js, .jsx, .json, .ts , and .tsx for bundling.
  • module
    We can enable webpack to load a particular file when requested by the app, using loaders. It takes a rules object that specifies that:

    • any file that ends with the extension .tsx or .ts should use awesome-typescript-loader to be loaded;
    • files that end with the .js extension should be loaded with source-map-loader;
    • files that end with the .css extension should be loaded with css-loader.
  • plugins
    Webpack has its own limitations, and it provides plugins to overcome them and extend its capabilities. For example, html-webpack-plugin creates a template file that is rendered to the browser from the index.html file in the ./src/component/index.html directory.

MiniCssExtractPlugin renders the parent CSS file of the app.

Adding Scripts To package.json

We can add different scripts to build React apps in our package.json file:

"scripts": {
"start": "webpack-dev-server --open",
"build": "webpack"
},

Now, run npm start in your CLI. If it all went well, you should see this:

React-Webpack setup output (Large preview)

If you have a knack for webpack, clone the repository for this setup, and use it across your projects.

Creating Files

Create a src folder and an index.tsx file. This will be the base file that renders React.

Now, if we run npm start, it will run our server and open a new tab. Running npm run build will build webpack for production and will create a build folder for us.

We have seen how to set up TypeScript from scratch using the Create React App and webpack configuration method.

One of the quickest ways to get a full grasp of TypeScript is by converting one of your existing vanilla React projects to TypeScript. Unfortunately, incrementally adopting TypeScript in an existing vanilla React project is stressful because it entails having to eject or rename all of the files, which would result in conflicts and a giant pull request if the project belonged to a large team.

Next, we’ll look at how to easily migrate a React project to TypeScript.

Migrate An Existing Create React App To TypeScript

To make this process more manageable, we’ll break it down into steps, which will enable us to migrate in individual chunks. Here are the steps we’ll take to migrate our project:

  1. Add TypeScript and types.
  2. Add tsconfig.json.
  3. Start small.
  4. Rename files extension to .tsx.
1. Add TypeScript to the Project

First, we’ll need to add TypeScript to our project. Assuming that your React project was bootstrapped with Create React App, we can run the following:

# Using npm
npm install --save typescript @types/node @types/react @types/react-dom @types/jest

# Using Yarn
yarn add typescript @types/node @types/react @types/react-dom @types/jest

Notice that we haven’t changed anything to TypeScript yet. If we run the command to start the project locally (npm start or yarn start), nothing changes. If that’s the case, then great! We’re ready for the next step.

2. Add the tsconfig.json File

Before taking advantage of TypeScript, we need to configure it via the tsconfig.json file. The simplest way to get started is to scaffold one using this command:

npx tsc --init

This gets us some basics, with a lot of commented code. Now, replace all of the code in tsconfig.json with this:

{
    "compilerOptions": {
      "jsx": "react",
      "module": "commonjs",
      "noImplicitAny": true,
      "outDir": "./build/",
      "preserveConstEnums": true,
      "removeComments": true,
      "sourceMap": true,
      "target": "es5"
    },
    "include": [
      "./src/**/**/*"
    ]
  }

TypeScript Configuration

Let’s also look at the different options we added to tsconfig.json:

  • compilerOptions
    Represents the different compiler options.

    • target
      Translates newer JavaScript constructs down to an older version, like ECMAScript 5.
    • lib
      Adds a list of library files to the compilation (for example, using es2015 allows us to use ECMAScript 6 syntax).
    • jsx:react
      Adds support for JSX in .tsx files.
    • lib
      Adds a list of library files to the compilation (for example, using es2015 allows us to use ECMAScript 6 syntax).
    • module
      Generates module code.
    • noImplicitAny
      Used to raise errors for declarations with an implied any type.
    • outDir
      Represents the output directory.
    • sourceMap
      Generates a .map file, which can be very useful for debugging our app.
    • include
      Used to specify the file list to be included.

Configurations options will vary, according to a project’s demand. You might need to check the TypeScript options spreadsheet to figure out what would fit your project.

We have only taken the required actions to get things ready. Our next step is to migrate a file to TypeScript.

3. Start With a Simple Component

Take advantage of TypeScript’s ability to be gradually adopted. Go one file at a time at your own pace. Do what makes sense for you and your team. Don’t try to tackle it all at once.

To properly convert this, we need to do two things:

  1. Change the file extension to .tsx.
  2. Add the type annotation (which would require some TypeScript knowledge).
4.Rename File Extensions to .tsx

In a large code base, it might seem tiring to rename files individually.

Rename multiples files on macOS

Renaming multiple files can be a time-waster. Here is how you can do it on a Mac. Right-click (or Ctrl + click, or click with two fingers simultaneously on the trackpad if you are using a MacBook) on the folder that contains the files you want to rename. Then, click “Reveal in Finder”. In the Finder, select all of the files you want to rename. Right-click the selected files, and choose “Rename X items…” Then, you will see something like this:

Rename files on a Mac (Large preview)

Insert the string you want to find, and the string with which you want to replace that found string, and hit “Rename”. Done.

Rename multiples files on Windows

Renaming multiple files on Windows is beyond the scope of this tutorial, but a complete guide is available.
You would usually get errors after renaming the files; you just need to add the type annotations. You can brush up on this in the documentation.

We have covered how to set up TypeScript in a React app. Now, let’s build an episode-picker app for Money Heist using TypeScript.

We won’t cover the basic types of TypeScript. Going through the documentation before continuing in this tutorial is required.

Time to Build

To make this process feel less daunting, we’ll break this down into steps, which will enable us to build the app in individual chunks. Here are all of the steps we’ll take to build the Money Heist episode-picker:

  • Scaffold a Create React App.
  • Fetch episodes.
    • Create the appropriate types and interfaces for our episodes in interface.ts.
    • Set up store for fetching episodes in store.tsx.
    • Create the action for fetching episodes in action.ts.
    • Create an EpisodeList.tsx component that holds the episodes fetched.
    • Import the EpisodesList component to our home page using React Lazy and Suspense.
  • Add episodes.
    • Set up store to add episodes in store.tsx.
    • Create the action for adding episodes in action.ts.
  • Remove episodes.
    • Set up store for deleting episodes in store.tsx.
    • Create the action for deleting episodes in action.ts.
  • Favorite episode.
    • Import EpisodesList component in favorite episode.
    • Render EpisodesList inside favorite episode.
  • Using Reach Router for navigation.

Set Up React

The easiest way to set up React is to use Create React App. Create React App is an officially supported way to create single-page React applications. It offers a modern build setup with no configuration.

We’ll make use of it to bootstrap the application we’ll be building. From your CLI, run the command below:

npx create-react-app react-ts-app && cd react-ts-app

Once the installation is successful, start the React server by running npm start.

React starter page (Large preview)

Understanding Interfaces And Types In Typescript

Interfaces in TypeScript are used when we need to give types to objects properties. Hence, we would be using interfaces to define our types.

interface Employee {
  name: string,
  role: string
  salary: number
}
const bestEmployee: Employee= {
  name: 'John Doe',
  role: 'IOS Developer',
  salary: '$8500'    //notice we are using a string
}

When compiling the code above, we would see this error: “Types of property salary are incompatible. Type string is not assignable to type number.”

Such errors happen in TypeScript when a property or variable is assigned a type other than the defined type. Specifically, the snippet above means that the salary property was assigned a string type instead of a number type.

Let’s create an interface.ts file in our src folder. Copy and paste this code into it:

/**
|--------------------------------------------------
| All the interfaces!
|--------------------------------------------------
*/
export interface IEpisode {
  airdate: string
  airstamp: string
  airtime: string
  id: number
  image: { medium: string; original: string }
  name: string
  number: number
  runtime: number
  season: number
  summary: string
  url: string
}
export interface IState {
  episodes: Array<IEpisode>
  favourites: Array<IEpisode>
}
export interface IAction {
  type: string
  payload: Array<IEpisode> | any
}
export type Dispatch = React.Dispatch<IAction>
export type FavAction = (
  state: IState,
  dispatch: Dispatch,
  episode: IEpisode
) => IAction

export interface IEpisodeProps {
  episodes: Array<IEpisode>
  store: { state: IState; dispatch: Dispatch }
  toggleFavAction: FavAction
  favourites: Array<IEpisode>
}
export interface IProps {
  episodes: Array<IEpisode>
  store: { state: IState; dispatch: Dispatch }
  toggleFavAction: FavAction
  favourites: Array<IEpisode>
}

It’s a good practice to add an “I” to the name of the interface. It makes the code readable. However, you may decide to exclude it.

IEpisode Interface

Our API returns a set of properties such as airdate, airstamp, airtime, id, image, name, number, runtime, season, summary, and url. Hence, we defined an IEpisode interface and set the appropriate data types to the object properties.

IState Interface

Our IState interface has episodes and favorites properties, respectively, and an Array interface.

IAction

The IAction interface properties are payload and type. The type property has a string type, while the payload has a type of Array | any.

Note that Array | any means an array of the episode interface or any type.

The Dispatch type is set to React.Dispatch and a interface. Note that React.Dispatch is the standard type for the dispatch function, according to the @types/react code base, while is an array of the Interface action.

Also, Visual Studio Code has a TypeScript checker. So, by merely highlighting or hovering over code, it’s smart enough to suggest the appropriate type.

In other words, for us to make use of our interface across our apps, we need to export it. So far, we have our store and our interfaces that hold the type of our object. Let’s now create our store.
Note that the other interfaces follow the same conventions as the ones explained.

Fetch Episodes

Creating a Store

To fetch our episodes, we need a store that holds the initial state of the data and that defines our reducer function.

We’ll make use of useReducer hook to set that up. Create a store.tsx file in your src folder. Copy and paste the following code into it.

import React, { useReducer, createContext } from 'react'
import { IState, IAction } from './types/interfaces'
const initialState: IState = {
  episodes: [],
  favourites: []
}
export const Store = createContext(initialState)
const reducer = (state: IState, action: IAction): IState => {
  switch (action.type) {
    case 'FETCH_DATA':
      return { ...state, episodes: action.payload }
    default:
      return state
  }
}
export const StoreProvider = ({ children }: JSX.ElementChildrenAttribute): JSX.Element => {
  const [state, dispatch] = useReducer(reducer, initialState)
  return {children}
}

The following ae the steps we’ve taken to create the store:

  • In defining our store, we need the [useReducer](https://reactjs.org/docs/hooks-reference.html#usereducer) hook and the createContext API from React, which is why we imported it.
  • We imported IState and IAction from ./types/interfaces.
  • We declared an initialState object with a type of IState, and properties of episodes and favorites, which are both set to an empty array, respectively.
  • Next, we created a Store variable that holds the createContext method and that is passed the initialState.

The createContext method type is , which means it could be a type of or any. We will see the any type used often in this article.

  • Next, we declared a reducer function and passed in state and action as parameters. The reducer function has a switch statement that checks the value of action.type. If the value is FETCH_DATA, then it returns an object that has a copy of our state (...state) and of the episode state that holds our action payload.
  • In the switch statement, we return a state of default.

Note that the state and action parameters in the reducer function have IState and IAction types, respectively. Also, the reducer function has a type of IState.

  • Lastly, we declared a StoreProvider function. This will give all components in our app access to the store.
  • This function takes children as a prop, and inside the StorePrivder function, we declared the useReducer hook.
  • We destructured state and dispatch.
  • In order to make our store accessible to all components, we passed in an object value containing state and dispatch.

The state that contains our episodes and favorites state will be made accessible by other components, while the dispatch is a function that changes the state.

  • We will export Store and StoreProvider, so that it can be used across our application.

Create Action.ts

We’ll need to make requests to the API to fetch the episodes that will be shown the user. This will be done in an action file. Create an Action.ts file, and then paste the following code:

import { Dispatch } from './interface/interfaces'
export const fetchDataAction = async (dispatch: Dispatch) => {
  const URL =
    'https://api.tvmaze.com/singlesearch/shows?q=la-casa-de-papel&embed=episodes'

  const data = await fetch(URL)
  const dataJSON = await data.json()
  return dispatch({
    type: 'FETCH_DATA',
    payload: dataJSON._embedded.episodes
  })
}

First, we need to import our interfaces so that they can be used in this file. The following steps were taken to create the action:

  • The fetchDataAction function takes dispatch props as a parameter.
  • Because our function is asynchronous, we would be using async and await.
  • We create a variable(URL) that holds our API endpoint.
  • We have another variable named data that holds the response from the API.
  • Then, we store the JSON response in dataJSON, after we have gotten the response in JSON format by calling data.json().
  • Lastly, we return a dispatch function that has a property of type and a string of FETCH_DATA. It also has a payload(). _embedded.episodes is the array of the episodes object from our endpoint.

Note that the fetchDataAction function fetches our endpoint, converts it to JSON objects, and returns the dispatch function, which updates the state declared earlier in the Store.

The exported dispatch type is set to React.Dispatch. Note that React.Dispatch is the standard type for the dispatch function according to the @types/react code base, while is an array of the Interface Action.

EpisodesList Component

In order to maintain the reusability of our app, we will keep all fetched episodes in a separate file, and then import the file in our homePage component.

In the components folder, create an EpisodesList.tsx file, and copy and paste the following code to it:

import React from 'react'
import { IEpisode, IProps } from '../types/interfaces'
const EpisodesList = (props: IProps): Array<JSX.Element> => {
  const { episodes } = props
  return episodes.map((episode: IEpisode) => {
    return (
      <section key={episode.id} className='episode-box'>
        <img src={!!episode.image ? episode.image.medium : ''} alt={`Money Heist ${episode.name}`} />
        <div>{episode.name}</div>
        <section style={{ display: 'flex', justifyContent: 'space-between' }}>
          <div>
            Season: {episode.season} Number: {episode.number}
          </div>
          <button
            type='button'
          >
            Fav
          </button>
        </section>
      </section>
    )
  })
}
export default EpisodesList
  • We import IEpisode and IProps from interfaces.tsx.
  • Next, we create an EpisodesList function that takes props. The props will have a type of IProps, while the function has a type of Array.

Visual Studio Code suggests that our function type be written as JSX.Element[].

Visual Studio Code suggests a type (Large preview)

While Array is equal to JSX.Element[], Array is called the generic identity. Hence, the generic pattern will be used often in this article.

  • Inside the function, we destructure the episodes from props, which has the IEpisode as a type.

Read about the generic identity, This knowledge will be needed as we proceed.

  • We returned the episodes props and mapped through it to return a few HTML tags.
  • The first section holds the key, which is episode.id, and a className of episode-box, which will be created later. We know that our episodes have images; hence, the image tag.
  • The image has a ternary operator that checks if there’s either an episode.image or an episode.image.medium. Else, we display an empty string if no image is found. Also, we included the episode.name in a div.

In section, we show the season that an episode belongs to and its number. We have a button with the text Fav. We’e exported the EpisodesList component so that we can use it across our app.

Home Page Component

We want the home page to trigger the API call and display the episodes using the EpisodesList component we created. Inside the components folder, create the HomePage component, and copy and paste the following code to it:

import React, { useContext, useEffect, lazy, Suspense } from 'react'
import App from '../App'
import { Store } from '../Store'
import { IEpisodeProps } from '../types/interfaces'
import { fetchDataAction } from '../Actions'
const EpisodesList = lazy<any>(() => import('./EpisodesList'))
  const HomePage = (): JSX.Element => {
  const { state, dispatch } = useContext(Store)
  useEffect(() => {
    state.episodes.length === 0 && fetchDataAction(dispatch)
  })
  const props: IEpisodeProps = {
    episodes: state.episodes,
    store: { state, dispatch }
  }
  return (
    <App>
      <Suspense fallback={<div>loading...</div>}>
        <section className='episode-layout'>
          <EpisodesList {...props} />
        </section>
      </Suspense>
    </App>
  )
  }
export default HomePage
  • We import useContext, useEffect, lazy, and Suspense from React. The imported app component is the bedrock upon which all other components must receive the value of the store.
  • We also import Store, IEpisodeProps, and FetchDataAction from their respective files.
  • We import the EpisodesList component using the React.lazy feature available in React 16.6.

React lazy loading supports the code-splitting convention. Thus, our EpisodesList component is loaded dynamically, instead of being loaded at once, thereby improving the performance of our app.

  • We destructure the state and dispatch as props from the Store.
  • The ampersand (&&) in the useEffect hook checks if our episodes state is empty (or equal to 0). Else, we return the fetchDataAction function.
  • Lastly, we return the App component. Inside it, we use the Suspense wrapper, and set fallback to a div with the loading text. This will be displayed to the user while we await the response from the API.
  • The EpisodesList component will mount when the data is available, and the data that will contain the episodes is what we spread into it.

Set Up Index.txs

The Homepage component needs to be a child of the StoreProvider. We’ll have to do that in the index file. Rename index.js to index.tsx and paste the following code:

import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'
import { StoreProvider } from './Store'
import HomePage from './components/HomePage'
ReactDOM.render(
  <StoreProvider>
      <HomePage />
  </StoreProvider>,
  document.getElementById('root')
)

We import StoreProvider, HomePage, and index.css from their respective files.
We wrap the HomePage component in our StoreProvider. This makes it possible for the Homepage component to access the store, as we saw in the previous section.

We have come a long way. Let’s check what the app looks like, without any CSS.

App without CSS (Large preview)

Create Index.css

Delete the code in the index.css file and replace it with this:

html {
  font-size: 14px;
}
body {
  margin: 0;
  padding: 0;
  font-size: 10px;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
    "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
    sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
.episode-layout {
  display: flex;
  flex-wrap: wrap;
  min-width: 100vh;
}
.episode-box {
  padding: .5rem;
}
.header {
  display: flex;
  justify-content: space-between;
  background: white;
  border-bottom: 1px solid black;
  padding: .5rem;
  position: sticky;
  top: 0;
}

Our app now has a look and feel. Here’s how it looks with CSS.

(Large preview)

Now we see that our episodes can finally be fetched and displayed, because we’ve adopted TypeScript all the way. Great, isn’t it?

Add Favorite Episodes Feature

Let’s add functionality that adds favorite episodes and that links it to a separate page. Let’s go back to our Store component and add a few lines of code:

Note that the highlighted code is newly added:

import React, { useReducer, createContext } from 'react'
import { IState, IAction } from './types/interfaces'
const initialState: IState = {
  episodes: [],
  favourites: []
}
export const Store = createContext<IState | any>(initialState)
const reducer = (state: IState, action: IAction): IState => {
  switch (action.type) {
    case 'FETCH_DATA':
      return { ...state, episodes: action.payload }
    case 'ADD_FAV':
      return { ...state, favourites: [...state.favourites, action.payload] }
    default:
      return state
  }
}
export const StoreProvider = ({ children }: JSX.ElementChildrenAttribute): JSX.Element => {
  const [state, dispatch] = useReducer(reducer, initialState)
  return <Store.Provider value={{ state, dispatch }}>{children}</Store.Provider>
}

To implement the “Add favorite” feature to our app, the ADD_FAV case is added. It returns an object that holds a copy of our previous state, as well as an array with a copy of the favorite state, with the payload.

We need an action that will be called each time a user clicks on the FAV button. Let’s add the highlighted code to index.tx:

import { IAction, IEpisode, Dispatch } from './types/interfaces'
export const fetchDataAction = async (dispatch: Dispatch) => {
  const URL =
    'https://api.tvmaze.com/singlesearch/shows?q=la-casa-de-papel&embed=episodes'

  const data = await fetch(URL)
  const dataJSON = await data.json()
  return dispatch({
    type: 'FETCH_DATA',
    payload: dataJSON._embedded.episodes
  })
}
export const toggleFavAction = (dispatch: any, episode: IEpisode | any): IAction => {
  let dispatchObj = {
    type: 'ADD_FAV',
    payload: episode
  }
  return dispatch(dispatchObj)
}

We create a toggleFavAction function that takes dispatch and episodes as parameters, and any and IEpisode|any as their respective types, with IAction as our function type. We have an object whose type is ADD_FAV and that has episode as its payload. Lastly, we just return and dispatch the object.

We will add some more snippets to EpisodeList.tsx. Copy and paste the highlighted code:

import React from 'react'
import { IEpisode, IProps } from '../types/interfaces'
const EpisodesList = (props: IProps): Array<JSX.Element> => {
  const { episodes, toggleFavAction, favourites, store } = props
  const { state, dispatch } = store

  return episodes.map((episode: IEpisode) => {
    return (
      <section key={episode.id} className='episode-box'>
        <img src={!!episode.image ? episode.image.medium : ''} alt={`Money Heist - ${episode.name}`} />
        <div>{episode.name}</div>
        <section style={{ display: 'flex', justifyContent: 'space-between' }}>
          <div>
            Seasion: {episode.season} Number: {episode.number}
          </div>
          <button
            type='button'
            onClick={() => toggleFavAction(state, dispatch, episode)}
          >
            {favourites.find((fav: IEpisode) => fav.id === episode.id)
              ? 'Unfav'
              : 'Fav'}
          </button>
        </section>
      </section>
    )
  })
}
export default EpisodesList

We include togglefavaction, favorites, and store as props, and we destructure state, a dispatch from the store. In order to select our favorite episode, we include the toggleFavAction method in an onClick event, and pass the state, dispatch and episode props as arguments to the function.

Lastly, we loop through the favorite state to check if fav.id(favorite ID) matches the episode.id. If it does, we toggle between the Unfav and Fav text. This helps the user know if they have favorited that episode or not.

We are getting close to the end. But we still need a page where favorite episodes can be linked to when the user chooses among the episodes on the home page.

If you’ve gotten this far, give yourself a pat on the back.

Favpage Component

In the components folder, create a FavPage.tsx file. Copy and paste the following code to it:

import React, { lazy, Suspense } from 'react'
import App from '../App'
import { Store } from '../Store'
import { IEpisodeProps } from '../types/interfaces'
import { toggleFavAction } from '../Actions'
const EpisodesList = lazy<any>(() => import('./EpisodesList'))
export default function FavPage(): JSX.Element {
  const { state, dispatch } = React.useContext(Store)
  const props: IEpisodeProps = {
    episodes: state.favourites,
    store: { state, dispatch },
    toggleFavAction,
    favourites: state.favourites
  }
  return (
    <App>
      <Suspense fallback={<div>loading...</div>}>
        <div className='episode-layout'>
          <EpisodesList {...props} />
        </div>
      </Suspense>
    </App>
  )
}

To create the logic behind choosing favorite episodes, we’ve written a little code. We import lazy and Suspense from React. We also import Store, IEpisodeProps, and toggleFavAction from their respective files.

We import our EpisodesList component using the React.lazy feature. Lastly, we return the App component. Inside it, we use the Suspense wrapper, and set a fallback to a div with the loading text.

This works similar to the Homepage component. This component will access the store to obtain the episodes the user has favorited. Then, the list of episodes gets passed to the EpisodesList component.

Let’s add a few more snippets to the HomePage.tsx file.

Include the toggleFavAction from ../Actions. Also include the toggleFavAction method as props.

import React, { useContext, useEffect, lazy, Suspense } from 'react'
import App from '../App'
import { Store } from '../Store'
import { IEpisodeProps } from '../types/interfaces'
import { fetchDataAction, toggleFavAction } from '../Actions'
const EpisodesList = lazy<any>(() => import('./EpisodesList'))
  const HomePage = (): JSX.Element => {
  const { state, dispatch } = useContext(Store)
  useEffect(() => {
    state.episodes.length === 0 && fetchDataAction(dispatch)
  })
  const props: IEpisodeProps = {
    episodes: state.episodes,
    store: { state, dispatch },
    toggleFavAction,
    favourites: state.favourites
  }
  return (
    <App>
      <Suspense fallback={<div>loading...</div>}>
        <section className='episode-layout'>
          <EpisodesList {...props} />
        </section>
      </Suspense>
    </App>
  )
  }
export default HomePage

Our FavPage needs to be linked, so we need a link in our header in App.tsx. To achieve this, we use Reach Router, a library similar to React Router. William Le explains the differences between Reach Router and React Router.

In your CLI, run npm install @reach/router @types/reach__router. We are installing both the Reach Router library and reach-router types.

Upon successful installation, import Link from @reach/router.

import React, { useContext, Fragment } from 'react'
import { Store } from './tsx'
import { Link } from '@reach/router'
 const App = ({
  children
}: {
  children: JSX.Element
   }): JSX.Element => {
   const { state } = useContext(Store)

  return (
    <Fragment>
      <header className='header'>
        <div>
          <h1>Money Heist</h1>
          <p>Pick your favourite episode</p>
        </div>
        <div>
          <Link to='/'>Home</Link>
          <Link to='/faves'>Favourite(s): {state.favourites.length}</Link>
        </div>
      </header>
      {children}
    </Fragment>
  )
 }
export default App

We destructure the store from useContext. Lastly, our home will have a Link and a path to /, while our favorite has a path to /faves.

{state.favourites.length} checks for the number of episodes in the favorites states and displays it.

Finally, in our index.tsx file, we import the FavPage and HomePage components, respectively, and wrap them in the Router.

Copy the highlighted code to the existing code:

import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'
import { StoreProvider } from './Store'
import { Router, RouteComponentProps } from '@reach/router'
import HomePage from './components/HomePage'
import FavPage from './components/FavPage'
const RouterPage = (
  props: { pageComponent: JSX.Element } & RouteComponentProps
) => props.pageComponent
ReactDOM.render(
  <StoreProvider>
   <Router>
      <RouterPage pageComponent={<HomePage />} path='/' />
      <RouterPage pageComponent={<FavPage />} path='/faves' />
    </Router>
  </StoreProvider>,
  document.getElementById('root')
)

Now, let’s see how the implemented ADD_FAV works.

The “Add favorite” code works (Large preview)

Remove Favorite Functionality

Finally, we will add the “Remove episode feature”, so that when the button is clicked, we toggle between adding or removing a favorite episode. We will display the number of episodes added or removed in the header.

STORE

To create the “Remove favorite episode” functionality, we will add another case in our store. So, go over to Store.tsx and add the highlighted code:

import React, { useReducer, createContext } from 'react'
import { IState, IAction } from './types/interfaces'
const initialState: IState = {
  episodes: [],
  favourites: []
}
export const Store = createContext<IState | any>(initialState)
const reducer = (state: IState, action: IAction): IState => {
  switch (action.type) {
    case 'FETCH_DATA':
      return { ...state, episodes: action.payload }
    case 'ADD_FAV':
      return { ...state, favourites: [...state.favourites, action.payload] }
    case 'REMOVE_FAV':
      return { ...state, favourites: action.payload }
    default:
      return state
  }
}
export const StoreProvider = ({ children }: JSX.ElementChildrenAttribute): JSX.Element => {
  const [state, dispatch] = useReducer(reducer, initialState)
  return {children}
}

We add yet another case named REMOVE_FAV and return an object containing the copy of our initialState. Also, the favorites state contains the action payload.

ACTION

Copy the following highlighted code and paste it in action.ts:

import { IAction, IEpisode, IState, Dispatch } from './types/interfaces'
export const fetchDataAction = async (dispatch: Dispatch) => {
  const URL =
    'https://api.tvmaze.com/singlesearch/shows?q=la-casa-de-papel&embed=episodes'

  const data = await fetch(URL)
  const dataJSON = await data.json()
  return dispatch({
    type: 'FETCH_DATA',
    payload: dataJSON._embedded.episodes
  })
}
//Add IState withits type
export const toggleFavAction = (state: IState, dispatch: any, episode: IEpisode | any): IAction => {
  const episodeInFav = state.favourites.includes(episode)
  let dispatchObj = {
    type: 'ADD_FAV',
    payload: episode
  }
  if (episodeInFav) {
    const favWithoutEpisode = state.favourites.filter(
      (fav: IEpisode) => fav.id !== episode.id
    )
    dispatchObj = {
      type: 'REMOVE_FAV',
      payload: favWithoutEpisode
    }
  }
  return dispatch(dispatchObj)
}

We import the IState interface from ./types/interfaces, because we’ll need to pass it as the type to the state props in the toggleFavAction function.

An episodeInFav variable is created to check if there’s an episode that exists in the favorites state.

We filter through the favorites state to check if a favorite ID doesn’t equal an episode ID. Thus, the dispatchObj is reassigned a type of REMOVE_FAV and a payload of favWithoutEpisode.

Let’s preview the result of our app.

Conclusion

In this article, we’ve seen how to set up TypeScript in a React project, and how to migrate a project from vanilla React to TypeScript.

We’ve also built an app with TypeScript and React to see how TypeScript is used in React projects.
I trust you were able to learn a few things.

Please do share your feedback and experiences with TypeScript in the comments section below. I’d love to see what you come up with!

The supporting repository for this article is available on GitHub.

References

  1. How To Migrate A React App To TypeScript,” Joe Previte
  2. Why And How To Use TypeScript In Your React App?,” Mahesh Haldar
Smashing Editorial(ks, ra, il, al)
Categories: Others Tags:

How to Own Your Audience by Creating an Email List

May 11th, 2020 No comments

Working in the field of email marketing means you’re always trying out new techniques to get your audience to click, right? It’s quite a fun task when you’re testing out new material, trying to get to that sweet point of content and selling. Email marketing gives you many scopes to play with, which is super engaging and rewarding too!

One of the most exciting parts of writing emails is creating an email list. You need to work around little intricate details, and by the end of it all, if you’re able to capture your audience’s imagination, it means you’re ready to sell effectively!

Having an email list of your audience is like owning them because it means you know precisely the kind of content they prefer. You can vary the frequency of the content you put out, and with time, you’ll be able to get them to interact with your brand and content!

Importance of Building a Good List in Email Marketing?

Email marketing is an excellent practice if you’re looking to build a brand on digital. More than 81% of SMBs depend on emails as their primary source of customer acquisition online. You can use it to get to know your customers’ personal preferences and then smartly weave your content accordingly to sell better to them.

Building a list for customers means they have entered their details on their own accord. It allows you to smartly segregate them based on how frequently they interact with your brand’s website and also gives them information on the new products and services you are offering.

Email list building gets up to 10x higher conversions than social media. The whole process of creating an email list is purposeful, personal, and rewarding for the customer. You can customize the content in such a way that it goes to them within a few hours or days of them browsing your site. If they’re a customer with a high frequency, then you can also use emails to give them special discounts.

Why Shouldn’t You Buy an Email List?

It’s crucial that you don’t ever purchase an email list. When you send an email to a customer, you are doing it out of consent, and they must give you their emails out of choice. The age-old adage of “the customer is king” applies here as well, and they need to feel validated when they sign-up to your content.

Also, it gives you the chance to nurture them from scratch and personalize offers, which can contribute to more sales. 74% of marketers say that targeted emails increase customer engagement rates, so they know what they’re talking about.

Buying an email list almost feels like you’re cheating and taking a shot in the dark. Put in the effort, and you’ll begin to see the awesome benefits it brings to your revenue. Created email lists can result in better ROIs for your company as well, so you’ll be well placed if you start nurturing your email list from scratch.

What are the Best Ways to Build Robust Email Lists?

There are many ways in which you can start the process of building a good email list. However, the most fundamental assets to building a great email list include –

  1. A blog – If you’re looking to engage your customers with some great content regularly, then build that blog! It’s a great way to showcase that you’re an expert when it comes to specific topics around your domain, and you can create your niche to stand out from the rest.

    For an excellent example of a blog owning a sphere, you can look at Neil Patel’s blogs. He knows his niche lies in the field of email marketing, and his tone and language are approachable. They are also driven by his experience and give that essential personal touch that resonates with his core audience of small to medium businesses.

    You can use this as a benchmark for finding your niche.

  2. The email marketing service – Your email marketing service is like the engine that ensures all of the fuel (content) is evenly distributed and keeps the machine going. You need to know precisely how to segregate your content and use the different features available to your benefit.

    Opting for a professional service allows you to free a lot of time as most of these services are automated. All you have to do is top them up by ensuring the email IDs are getting segregated in time, and they’ll take care of the rest.

    Mailchimp is one such service that provides great benefits and tools, but there are others available in the market as well. These sites, of course, come with a fee, and it’s important that you think of them as a long-term investment. If you want to look for other providers, you can give these alternatives to Mailchimp a try.

    We’ve used SendX and ActiveCampaign, and their smartly-enabled features stand out from the other competitors in the market.

  3. Opt-in and out – Allowing your customers to opt-in or out of an email list means you’re giving them the power, and they will undoubtedly appreciate the same. On any email you send them, you need to provide them with a button that says “Opt-out” so they have a feeling of the upper hand.

    There are many more factors to building a good email list, including testimonials, subscription confirmation, and more.

    We’ve worked with emails where the option to opt-in or out has worked in our favor. Consumers have gone and clicked on the opt-in button, which shows us that our content is working well.

Success Stories of Businesses with a Small But Highly Targeted Email List

1. The Hell Yeah Group – The Hell Yeah Group shares its weekly newsletter that summarizes the entire financial news. The best part is that they share the content that they’ve made themselves, and this makes it simpler for readers to directly consume it instead of going to different sites. The highly targeted email list is pointed towards workers in the financial industry and is a great example –

2. Away – They began as a small start-up, but Away is now valued at over $1.4 billion! Their beautiful emails are one of the reasons why their customers love them, and you can see for yourself. By including a type of “wanderlust” feel, they’ve been able to capture the imagination and get people to subscribe and buy from their newsletters.

Thus, with these techniques, you’ll be able to create valuable emails that convert for you. Remember to work with a multitude of options for content, style, and, most importantly, nurturing your emails. This makes it simpler to create reliable lists and generate consistent revenue.

To Conclude

Thus, the power of the email list is real and all-encompassing. Not only does it help you identify the best customers and segregate them, but it also enables you to trigger emails based on their behavior.

Using a strong email list, having targeted social media advertising and writing the right content can go a long way in acquiring customers. Don’t forget to delight existing customers as well, as returning customers can go a long way in giving you regular revenue. Work right, keep experimenting, and you’ll see the results soon enough! Good luck!


Marketing vector created by stories – www.freepik.com

Categories: Others Tags:

How can you reduce mobile app development cost for startups in 2020?

May 11th, 2020 No comments

In the current mobile age, people are connected to the internet all the time. This is the main reason behind companies investing in startups and development of mobile applications.

Mobile applications have become the core of the business world. The increase in demand for business applications has also increased the development cost of applications. Every business cannot afford huge development cost, especially the small companies and startups. However, that should not stop startups from taking benefits of mobile applications and grow their business.

From big companies to small startups, all are benefiting by the services provided by the app development companies to generate strategies for mobile app development. In this blog, we are going to discuss some of these strategies you can follow to reduce the mobile app development cost for startups in 2020.

Let us begin discussing these strategies now.

1. Listing the project requirements

It is essential to list down all the requirements of the app. The documentation helps the app development companies to understand the requirements of the product clearly. Detailed documentation reduces the cost of the app development and also saves a lot of development time.

Documenting the project requirements is extremely helpful in the whole development process.

2. Budgeting

Budgeting is essential no matter what the size of business you have. You have to give enough time and efforts to select the trusted app development company. The budgeting has to be done carefully before hiring any app development company and finalizing the price. You haveto make sure that the quality of the services does not get compromised.

3. Outsourcing the project

You can reduce the application cost by a considerable margin if you outsource the app development company. It will bring great success if an application or startups is outsourced to an app development company for development because of the amount of technical knowledge and experience. Try to get in touch with the best application development company for outsourcing. Make sure that the company is dedicated and will stay in touch throughout the project.

4. Tracking reviews and ratings

Every mobile app development company will have a series of ratings and reviews. These ratings and reviews are informative as they allow connecting with the previous clients and their experience with the company and get knowledge about the working style and services of the concerned app developing company.

5. Communication flow

The right communication flow in any app development project is essential. There needs to be communication between you and the development team as it will help you in and the development team to know what exactly you need in your app. Keeping a track on development process will also have an impact on the cost of development. This communication will enable them to start any new feature or stop any function that doesn’t fit in the budget of app development.

6. Simple and elegant UI/UX

One of the best strategies to reduce application development cost is by going for a simple UI/UX of the app. complex design confuses the users, and the app doesn’t appear to be understandable, other than that, complex deigns also cost much. So, going for a simple and elegant UI/UX design to reduce the development cost is a smart idea.

7. Cross-platform development

This is one of the most influential factors that effect app development cost. Most of the apps are built on Android because of its vast market share in the world. If you go for app development on the iOS platform, it would cost you a lot.

To resolve this issue, the best option is to go for a cross-platform application that supports both Android as well as iOS.

8. Pre-launch testing

Make sure to thoroughly test the application before launching it. It is advised that the app is checked properly before it is launched in the market. Testing the app also gives enough time for identifying if there are any bugs in the app. If the application is launched without proper testing, the brand might lose its reputation if there is some issue in the app.

Therefore, testing the app will save you from all the unnecessary chaos and will keep your money as well as time.

9. Proper maintenance

Last but not least, maintenance plays an essential role in the overall development process. An application needs regular maintenance to run it smoothly. Hire a dedicated developer to help you with troubleshooting your app regularly.

If regular maintenance is provided to the app, no major issues will occur, and therefore, the site will run smoothly without any errors.

Final thoughts

By following all these factors, you can significantly reduce your mobile app development costs. Follow these app development cost-reduction strategies this year, and you will see how your business grows. Just make sure to hire a trusted mobile app development company to get the best benefits.

If you are planning to build a mobile app of your own, then Metizsoft Solution, a mobile app development company can be helpful to you.

We will offer excellent services that too at cost-effective rates. Think no more, get in touch with us today.


Photo by freestocks on Unsplash

Categories: Others Tags:

Facing Up To Remote Reality: How AR And VR Is Reshaping Remote Work

May 11th, 2020 No comments

The world of remote work is gathering momentum. The devastating impact of Coronavirus around the world has forced businesses to look into ways of keeping productive while employees stay safe at home. Widespread rethinks of how staff communicate with colleagues and maintain performance levels are imperative as companies look to adapt.

Remote work is here to stay, regardless of whether we’re facing up to lockdowns or are safely able to access our offices. But is it possible for businesses to communicate effectively with key staff operating away from a designated place of work?

Technology has made working from home possible, and advances in both augmented reality and virtual reality could pave the way for richer experiences than ever before.

The beauty of both AR and VR when it comes to remote collaboration and productivity is that it can create a multi-dimensional immersive experience for users, regardless of where they’re based.

Today, technology is already arriving that can digitally transport users into a virtual meeting room where rich information can be shared much faster than in face-to-face environments, with much more visual detail.

The arrival of AR and VR remote work can even help businesses to cut costs on office supplies and utilities – without the need of accommodating entire workforces onto office servers. While the removal of commutes can carry benefits for the health of employees and the environment alike.

Circumstances have forced the business world to evolve at a faster rate, and here’s how AR and VR can play an influential role in reshaping our perceptions of remote work:

Immersive Meetings

Most industries are built on some degree of communication between colleagues, clients and customers. These communicative measures have been difficult to uphold for companies looking to transition into remote work or enabling working from home (WFH) among employees.

Video conferencing solutions are gaining in popularity among remote businesses, and are an effective way or replicating face-to-face environments for users. However, it’s difficult for workers to share ideas in real-time and the technology often fails to provide an engaging platform for group meetings.

AR and VR can make a significant difference in alleviating the limitations of remote meetings. Platforms like MeetinVR allow users to build their own 3D avatars and turn to multidimensional model rendering to help bring life to their discussions.

While there are plenty of instant messaging and collaboration platforms available for employees to discuss their ideas, no technology has the power to provide virtual walkthroughs of designs and diagrams as much as virtual reality infused software.

Augmented reality is a key player in terms of bringing immersive meetings to businesses. Applications like Scope AR illustrate how users can interact and collaborate in real-time with real-world visual cues. Because AR overlays digital information on top of real-life environments, Scope AR helps a range of industries to assist staff remotely by adding digital information to a user’s line of vision.

Comprehensive Training

Due to the speed in which visual and 3D information can be shown to users, virtual reality has become a significant player in remote training for businesses.

VR helps to immerse staff into virtual presentation halls with built-in training programs and an array of engaging visual experiences to keep users tuned in.

One of the leading examples of VR education and training platforms can be found in ENGAGE. Providing businesses with the ability to host meetings, presentations, classes and events with as many as 50 remote participants, ENGAGE allows managers to build comprehensive experiences for users in a matter of minutes with its suite of tools.

It’s even possible for staff to record their hosting sessions in order to deliver the experience to others later on. The platform has an extensive library of 3D objects that can be used for training sessions, and users can even change their virtual backdrops and add effects into their modules.

Everybody has different approaches to learning, and the beauty of both AR and VR is that adaptive settings and content can be changed depending on the preference of employees. In a world that’s becoming increasingly remote, VR training platforms can pave the way for an experience that offers greater engagement than in-house training programs.

Visual Collaboration

The primary issue with the commonplace Skype and Zoom video meetings that have been popular at the beginning of the year is that users still lose out on interpreting valuable body language that helps to emphasise points or demonstrate sympathy.

Employees can suffer when visual cues are lost due to a low-definition webcam or missed expressions.

The immersive experience offered by AR and VR platforms has the power to hurl users into an environment where every participant is fully engaged in their surroundings with no distractions lurking off-screen.

Here, meeting participants and trainees alike are fully focused on their vision as 3D avatars and detailed renderings provide informative and enlightening feedback.

As the values of remote work become increasingly apparent, businesses will need to look with increasing urgency towards facilitating the most immersive technology to support the WFH transition. In AR and VR, the solution looks set to be even better than our face-to-face past.


Photo by Patrick Schneider on Unsplash

Categories: Others Tags:

Popular Design News of the Week: May 4, 2020 – May 10, 2020

May 10th, 2020 No comments

Every week users submit a lot of interesting stuff on our sister site Webdesigner News, highlighting great content from around the web that can be of interest to web designers.

The best way to keep track of all the great stories and news being posted is simply to check out the Webdesigner News site, however, in case you missed some here’s a quick and useful compilation of the most popular designer news that we curated from the past week.

Unconventional Tips to Improve Open Rates in 2020

COVID-19: The Ultimate Design Thinking Use Case

Slack is Silently Testing a Drastically Redesigned Interface in its Latest App Beta

Exciting Things on the Horizon for CSS Layout

The Huge List of Code You Need to Write to Start a SaaS

8 Awesome Examples of ‘No Results Found’ Pages

Responsive Grids and How to Actually Use Them

Sitesauce: Static Website Generator

7 Must-know Tips for Incorporating Photography in UI Design

5 Design Quotes that Illustrate Modern UX Practices

Building Client-Proof WordPress Websites

3 Ways Digital Marketing Agencies will Change Due to COVID-19

Color Theme Switcher

How Culture Impacts UX Design

How to Easily Create a Responsive Vertical Rhythm with CSS

Best Blog Designs I Want to Steal Everything from

Designer Slack Communities

Kontrapunkt

The Pragmatic Designer: Local and Self Hosted Design Tools

How I Redesigned my College’s Students Application

When Bad UX is Good

Inside the Redesign of ‘Fast Company’ Magazine

A Systems View of Brand Design

A 9-Step Professional Design Process Explained

6 Design Challenges for You and your Team

Want more? No problem! Keep track of top design news from around the web with Webdesigner News.

Source

Categories: Designing, Others Tags:

Chromium lands Flexbox gap

May 8th, 2020 No comments

I mentioned this the other day via Michelle Barker’s coverage, but here I’ll link to the official announcement. The main thing is that we’ll be getting gap with flexbox, which means:

.flex-parent {
  display: flex;
  gap: 1rem;
}
.flex-child {
  flex: 1;
}

That’s excellent, as putting space in between flex items has been tough in the past. We have justify-content: space-between, which is nice sometimes, but that doesn’t allow you to explicitly tell the flex container how much space you want. For that, we’d typically use margin, but that means avoiding setting the margin on the first or last element depending on the direction of the margin — which is annoying gets complicated.

We have gap in CSS Grid and it’s way better. It’s great to have it in flexbox.

But it’s going to get weird for a minute. Safari doesn’t support it yet (nor stable Chrome) so we can’t just plop it out there and expect it to work with flexbox. But shouldn’t we be able to do an @supports query these days?

/* Nope, sorry. This "works" but it doesn't 
   actually tell you if it works in *flexbox* or not.
   This works in grid in most browsers now, so it will pass. */
@supports (gap: 1rem) {
  .flex-parent {
     gap: 1rem;
  }
}

That got weird because grid-gap was dropped in favor of just gap. I’m sure grid-gap will be supported forever because that’s generally how these things go, but we’re encouraged to use gap instead. So, you might say gap is a little overloaded, but that should shake out over time (a year?). It’s complicated a smidge more by the fact that column-gap is now going to gap as well. gap has a whole bunch of jobs.

I’d say I’m still in favor of the change, despite the overloading. Simpler mental modals are important for the long-term, and there isn’t exactly anything coming up to challenge CSS for styling in the browser. I’d bet my 2-year old daughter writes some CSS in her lifetime.

Direct Link to ArticlePermalink

The post Chromium lands Flexbox gap appeared first on CSS-Tricks.

Categories: Designing, Others Tags:

prerender.js

May 8th, 2020 No comments

This is another player in the game of rendering the page of the link that you’re about to click on before you click it. It’s like getting a decent performance boost for extremely little effort.

Instant.page is another one, and I’ve been sufficiently convinced by its methodology to the extent that I run it here on this site right now. I don’t really know the difference between the two. And they aren’t the only players either. Google has quicklink and there’s guess-js for really exotic preloading.

It’s a bit of a pity that Safari and Firefox don’t support , as it really seems to me the absolute easiest way to pull this off would be to drop that on the page where, on mouseover of a link, it points to the href of that link.

Direct Link to ArticlePermalink

The post prerender.js appeared first on CSS-Tricks.

Categories: Designing, Others Tags:

Let’s Take a Deep Dive Into the CSS Contain Property

May 8th, 2020 No comments
DevTools showing set time at 27.9 milliseconds which is the same as the total time to recalculate styles.

Compared to the past, modern browsers have become really efficient at rendering the tangled web of HTML, CSS, and JavaScript code a typical webpage provides. It takes a mere milliseconds to render the code we give it into something people can use.

What could we, as front-end developers, do to actually help the browser be even faster at rendering? There are the usual best practices that are so easy to forget with our modern tooling — especially in cases where we may not have as much control over generated code. We could keep our CSS under control, for instance, with fewer and simpler selectors. We could keep our HTML under control; keep the tree flatter with fewer nodes, and especially fewer children. We could keep our JavaScript under control; while being careful with our HTML and CSS manipulations.

Actually, modern frameworks such as Vue and React do help out a good bit with that last part.

I would like to explore a CSS property that we could use to help the browser figure out what calculations it can reduce in priority or maybe even skip altogether.

This property is called contain. Here is how MDN defines this property:

The contain CSS property allows an author to indicate that an element and its contents are, as much as possible, independent of the rest of the document tree. This allows the browser to recalculate layout, style, paint, size, or any combination of them for a limited area of the DOM and not the entire page, leading to obvious performance benefits.

A simple way to look at what this property provides is that we can give hints to the browser about the relationships of the various elements on the page. Not necessarily smaller elements, such as paragraphs or links, but larger groups such as sections or articles. Essentially, we’re talking about container elements that hold content — even content that can be dynamic in nature. Think of a typical SPA where dynamic content is being inserted and removed throughout the page, often independent of other content on the page.

A browser cannot predict the future of layout changes to the webpage that can happen from JavaScript inserting and removing content on the page. Even simple things as inserting a class name to an element, animating a DOM element, or just getting the dimensions of an element can cause a reflow and repaint of the page. Such things can be expensive and should be avoided, or at least be reduced as much as possible.

Developers can sort of predict the future because they’ll know about possible future changes based on the UX of the page design, such as when the user clicks on a button it will call for data to be inserted in a div located somewhere in the current view. We know that’s a possibility, but the browser does not. We also know that there’s a distinct possibility that inserting data in that div will not change anything visually, or otherwise, for other elements on the page.

Browser developers have spent a good amount of time optimizing the browser to handle such situations. There are various ways of helping the browser be more efficient in such situations, but more direct hints would be helpful. The contain property gives us a way to provide these hints.

The various ways to contain

The contain property has three values that can be used individually or in combination with one another: size, layout, and paint. It also has two shorthand values for common combinations: strict and content. Let’s cover the basics of each.

Please keep in mind that there are a number of rules and edge cases for each of these that are covered in the spec. I would imagine these will not be of much concern in most situations. Yet, if you get an undesired result, then a quick look at the spec might be handy.

There is also a style containment type in the spec that this article will not cover. The reason being that the style containment type is considered of little value at this time and is currently at-risk of being removed from the spec.

Size containment

size containment is actually a simple one to explain. When a container with this containment is involved in the layout calculations, the browser can skip quite a bit because it ignores the children of that container. It is expected the container will have a set height and width; otherwise, it collapses, and that is the only thing considered in layout of the page. It is treated as if it has no content whatsoever.

Consider that descendants can affect their container in terms of size, depending on the styles of the container. This has to be considered when calculating layout; with size containment, it most likely will not be considered. Once the container’s size has been resolved in relation to the page, then the layout of its descendants will be calculated.

size containment doesn’t really provide much in the way of optimizations. It is usually combined with one of the other values.

Although, one benefit it could provide is helping with JavaScript that alters the descendants of the container based on the size of the container, such as a container query type situation. In some circumstances, altering descendants based on the container’s size can cause the container to change size after the change was done to the descendants. Since a change in the container’s size can trigger another change in the descendants you could end up with a loop of changes. size containment can help prevent that loop.

Here’s a totally contrived example of this resizing loop concept:

CodePen Embed Fallback

In this example, clicking the start button will cause the red box to start growing, based on the size of the purple parent box, plus five pixels. As the purple box adjusts in size, a resize observer tells the red square to again resize based on the size of the parent. This causes the parent to resize again and so on. The code stops this process once the parent gets above 300 pixels to prevent the infinite loop.

The reset button, of course, puts everything back into place.

Clicking the checkbox “set size containment” sets different dimensions and the size containment on the purple box. Now when you click on the start button, the red box will resize itself based on the width of the purple box. True, it overflows the parent, but the point is that it only resizes the one time and stops; there’s no longer a loop.

If you click on the resize container button, the purple box will grow wider. After the delay, the red box will resize itself accordingly. Clicking the button again returns the purple box back to its original size and then the red box will resize again.

While it is possible to accomplish this behavior without use of the containment, you will miss out on the benefits. If this is a situation that can happen often in the page the containment helps out with page layout calculations. When the descendants change internal to the containment, the rest of the page behaves as if the changes never happened.

Layout containment

layout containment tells the browser that external elements neither affect the internal layout of the container element, nor does the internal layout of the container element affect external elements. So when the browser does layout calculations, it can assume that the various elements that have the layout containment won’t affect other elements. This can lower the amount of calculations that need to be done.

Another benefit is that related calculations could be delayed or lowered in priority if the container is off-screen or obscured. An example the spec provides is:

[…] for example, if the containing box is near the end of a block container, and you’re viewing the beginning of the block container

The container with layout containment becomes a containing box for absolute or fixed position descendants. This would be the same as applying a relative position to the container. So, keep that in mind how the container’s descendants may be affected when applying this type of containment.

On a similar note, the container gets a new stacking context, so z-index can be used the same as if a relative, absolute, or fixed position was applied. Although, setting the top, right, bottom, or left properties has no effect on the container.

Here’s a simple example of this:

CodePen Embed Fallback

Click the box and layout containment is toggled. When layout containment is applied, the two purple lines, which are absolute positioned, will shift to inside the purple box. This is because the purple box becomes a containing block with the containment. Another thing to note is that the container is now stacked on top of the green lines. This is because the container now has a new stacking context and follows those rules accordingly.

Paint containment

paint containment tells the browser none of the children of the container will ever be painted outside the boundaries of the container’s box dimensions. This is similar to placing overflow: hidden; on the container, but with a few differences.

For one, the container gets the same treatment as it does under layout containment: it becomes a containing block with its own stacking context. So, having positioned children inside paint containment will respect the container in terms of placement. If we were to duplicate the layout containment demo above but use paint containment instead, the outcome would be much the same. The difference being that the purple lines would not overflow the container when containment is applied, but would be clipped at the container’s border-box.

Another interesting benefit of paint containment is that the browser can skip that element’s descendants in paint calculations if it can detect that the container itself is not visible within the viewport. If the container is not in the viewport or obscured in some way, then it’s a guarantee that its descendants are not visible as well. As an example, think of a nav menu that normally sits off-screen to the left of the page and it slides in when a button is clicked. When that menu is in its normal state off-screen, the browser just skips trying to paint its contents.

Containments working together

These three containments provide different ways of influencing parts of rendering calculations performed by the browser. size containment tells the browser that this container should not cause positional shifting on the page when its contents change. layout containment tells the browser that this container’s descendants should not cause layout changes in elements outside of its container and vice-versa. paint containment tells the browser that this container’s content will never be painted outside of the container’s dimensions and, if the container is obscured, then don’t bother painting the contents at all.

Since each of these provide different optimizations, it would make sense to combine some of them. The spec actually allows for that. For example, we could use layout and paint together as values of the contain property like this:

.el {
  contain: layout paint;
}

Since this is such an obvious thing to do, the spec actually provides two shorthand values:

Shorthand Longhand
content layout paint
strict layout paint size

The content value will be the most common to use in a web project with a number of dynamic elements, such as large multiple containers that have content changing over time or from user activity.

The strict value would be useful for containers that have a defined size that will never change, even if the content changes. Once in place, it’ll stay the intended size. A simple example of that is a div that contains third-party external advertising content, at industry-defined dimensions, that has no relation to anything else on the page DOM-wise.

Performance benefits

This part of the article is tough to explain. The problem is that there isn’t much in the way of visuals about the performance benefits. Most of the benefits are behind-the-scenes optimizations that help the browser decide what to do on a layout or paint change.

As an attempt to show the contain property’s performance benefits, I made a simple example that changes the font-size on an element with several children. This sort of change would normally trigger a re-layout, which would also lead to a repaint of the page. The example covers the contain values of none, content, and strict.

CodePen Embed Fallback

The radio buttons change the value of the contain property being applied to the purple box in the center. The “change font-size” button will toggle the font-size of the contents of the purple box by switching classes. Unfortunately, this class change is also a potential trigger for re-layout. If you’re curious, here is a list of situations in JavaScript and then a similar list for CSS that trigger such layout and paint calculations. I bet there’s more than you think.

My totally unscientific process was to select the contain type, start a performance recording in Chome’s developer tools, click the button, wait for the font-size change, then stop the recording after another second or so. I did this three times for each containment type to be able to compare multiple recordings. The numbers for this type of comparison are in the low milliseconds each, but there’s enough of a difference to get a feel for the benefits. The numbers could potentially be quite different in a more real-world situation.

But there are a few things to note other than just the raw numbers.

When looking through the recording, I would find the relevant area in the timeline and focus there to select the task that covers the change. Then I would look at the event log of the task to see the details. The logged events were: recalculate style, layout, update layer tree, paint, and composite layers. Adding the times of all those gives us the total time of the task.

The event log with no containment.

One thing to note for the two containment types is that the paint event was logged twice. I’ll get back to that in a moment.

DevTools showing set time at 13.8 milliseconds which is the same as the total time to recalculate styles.

Completing the task at hand

Here are the total times for the three containment types, three runs each:

Containment Run 1 Run 2 Run 3 Average
none 24 ms 33.8 ms 23.3 ms 27.03 ms
content 13.2 ms 9 ms 9.2 ms 10.47 ms
strict 5.6 ms 18.9 ms 8.5 ms 11 ms

The majority of the time was spent in layout. There were spikes here and there throughout the numbers, but remember that these are unscientific anecdotal results. In fact, the second run of strict containment had a much higher result than the other two runs; I just kept it in because such things do happen in the real world. Perhaps the music I was listening to at the time changed songs during that run, who knows. But you can see that the other two runs were much quicker.

So, by these numbers you can start to see that the contain property helps the browser render more efficiently. Now imagine my one small change being multiplied over the many changes made to the DOM and styling of a typical dynamic web page.

Where things get more interesting is in the details of the paint event.

Layout once, paint twice

Stick with me here. I promise it will make sense.

I’m going to use the demo above as the basis for the following descriptions. If you wish to follow along then go to the full version of the demo and open the DevTools. Note that you have to open up the details of the “frame” and not the “main” timeline once you run the performance tool to see what I’m about to describe.

Showing frame details open and main details closed in DevTools.
Showing frame details open and main details closed in DevTools

I’m actually taking screenshots from the “fullpage” version since DevTools works better with that version. That said, the regular “full” version should give roughly the same idea.

The paint event only fired once in the event log for the task that had no containment at all. Typically, the event didn’t take too long, ranging from 0.2 ms to 3.6 ms. The deeper details is where it gets interesting. In those details, it notes that the area of paint was the entire page. In the event log, if you hover on the paint event, DevTools will even highlight the area of the page that was painted. The dimensions in this case will be whatever the size of your browser viewport happens to be. It will also note the layer root of the paint.

Showing DevTools paint calculation of 0.7 milliseconds.
Paint event details

Note that the page area to the left in the image is highlighted, even outside of the purple box. Over to the right, are the dimensions of the paint to the screen. That’s roughly the size of the viewport in this instance. For a future comparison, note the #document as the layer root.

Keep in mind that browsers have the concept of layers for certain elements to help with painting. Layers are usually for elements that may overlap each other due to a new stacking context. An example of this is the way applying position: relative; and z-index: 1; to an element will cause the browser to create that element as a new layer. The contain property has the same effect.

There is a section in DevTools called “rendering” and it provides various tools to see how the browser renders the page. When selecting the checkbox named “Layer borders” we can see different things based on the containment. When the containment is none then you should see no layers beyond the typical static web page layers. Select content or strict and you can see the purple box get converted to its own layer and the rest of the layers for the page shift accordingly.

Layers with no containment
Layers with containment

It may be hard to notice in the image, but after selecting content containment the purple box becomes its own layer and the page has a shift in layers behind the box. Also notice that in the top image the layer line goes across on top of the box, while in the second image the layer line is below the box.

I mentioned before that both content and strict causes the paint to fire twice. This is because two painting processes are done for two different reasons. In my demo the first event is for the purple box and the second is for the contents of the purple box.

Typically the first event will paint the purple box and report the dimensions of that box as part of the event. The box is now its own layer and enjoys the benefits that applies.

The second event is for the contents of the box since they are scrolling elements. As the spec explains; since the stacking context is guaranteed, scrolling elements can be painted into a single GPU layer. The dimensions reported in the second event is taller, the height of the scrolling elements. Possibly even narrower to make room for the scrollbar.

First paint event with content containment
Second paint event with content containment

Note the difference in dimensions on the right of both of those images. Also, the layer root for both of those events is main.change instead of the #document seen above. The purple box is a main element, so only that element was painted as opposed as to whole document. You can see the box being highlighted as opposed to the whole page.

The benefits of this is that normally when scrolling elements come into view, they have to be painted. Scrolling elements in containment have already been painted and don’t require it again when coming into view. So we get some scrolling optimizations as well.

Again, this can be seen in the demo.

Back to that Rendering tab. This time, check “Scrolling performance issue” instead. When the containment is set to none, Chrome covers the purple box with an overlay that’s labeled “repaints on scroll.”

DevTools showing “repaints on scroll” with no containment

If you wish to see this happen live, check the “Paint flashing” option.

Please note: if flashing colors on the screen may present an issue for you in some way, please consider not checking the “Paint flashing” option. In the example I just described, not much changes on the page, but if one were to leave that checked and visited other sites, then reactions may be different.

With paint flashing enabled, you should see a paint indicator covering all the text within the purple box whenever you scroll inside it. Now change the containment to content or strict and then scroll again. After the first initial paint flash it should never reappear, but the scrollbar does show indications of painting while scrolling.

Paint flashing enabled and scrolling with no containment
Paint flashing and scrolling with content containment

Also notice that the “repaints on scroll” overlay is gone on both forms of containment. In this case, containment has given us not only some performance boost in painting but in scrolling as well.

An interesting accidental discovery

As I was experimenting with the demo above and finding out how the paint and scrolling performance aspects worked, I came across an interesting issue. In one test, I had a simple box in the center of page, but with minimal styling. It was essentially an element that scrolls with lots of text content. I was applying content containment to the container element, but I wasn’t seeing the scrolling performance benefits described above.

The container was flagged with the “repaints on scroll” overlay and the paint flashing was the same as no containment applied, even though I knew for a fact that content containment was being applied to the container. So I started comparing my simple test against the more styled version I discussed above.

I eventually saw that if the background-color of the container is transparent, then the containment scroll performance benefits do not happen.

I ran a similar performance test where I would change the font-size of the contents to trigger the re-layout and repaint. Both tests had roughly the same results, with only difference that the first test had a transparent background-color and the second test had a proper background-color. By the numbers, it looks like the behind-the-scenes calculations are still more performant; only the paint events are different. It appears the element doesn’t become its own layer in the paint calculations with a transparent background-color.

The first test run only had one paint event in the event log. The second test run had the two paint events as I would expect. Without that background color, it seems the browser decides to skip the layer aspect of the containment. I even found that faking transparency by using the same color as the color behind the element works as well. My guess is if the container’s background is transparent then it must rely on whatever is underneath, making it impossible to separate the container to its own paint layer.

I made another version of the test demo that changes the background-color of the container element from transparent to the same color used for the background color of the body. Here are two screenshots showing the differences when using the various options in the Rendering panel in DevTools.

Rendering panel with transparent background-color

You can see the checkboxes that have been selected and the result to the container. Even with a content containment applied, the box has “repaints on scroll” as well as the green overlay showing painting while scrolling.

Rendering panel with background-color applied

In the second image, you can see that the same checkboxes are selected and a different result to the container. The “repaints on scroll” overlay is gone and the green overlay for painting is also gone. You can see the paint overlay on the scrollbar to show it was active.

Conclusion: make sure to apply some form of background color to your container when applying containment to get all the benefits.

Here’s what I used for the test:

CodePen Embed Fallback

This is the bottom of the page

This article has covered the basics of the CSS contain property with its values, benefits, and potential performance gains. There are some excellent benefits to applying this property to certain elements in HTML; which elements need this applied is up to you. At least, that’s what I gather since I’m unaware of any specific guidance. The general idea is apply it to elements that are containers of other elements, especially those with some form of dynamic aspect to them.

Some possible scenarios: grid areas of a CSS grid, elements containing third-party content, and containers that have dynamic content based on user interaction. There shouldn’t be any harm in using the property in these cases, assuming you aren’t trying to contain an element that does, in fact, rely in some way on another element outside that containment.

Browser support is very strong. Safari is the only holdout at this point. You can still use the property regardless because the browser simply skips over that code without error if it doesn’t understand the property or its value.

So, feel free to start containing your stuff!

The post Let’s Take a Deep Dive Into the CSS Contain Property appeared first on CSS-Tricks.

Categories: Designing, Others Tags: