Archive

Archive for July, 2020

Exciting New Tools for Designers, July 2020

July 13th, 2020 No comments

Some of the changes we are seeing with where we work are starting to pop up in the type of new tools made for designers and developers. More tools with remote collaboration as a key feature are increasing in popularity. (You’ll find a few of those here.)

Here’s what new for designers this month.

Webdesign Toolbox

Webdesign Toolbox is a collection of tools, apps, and resources all in one location for designers and developers. The best part of this resource is that it is human-curated, so every tool is quality checked and makes the list because it has been tested and researched. Search the collection by design, dev, stock, typography, UX, or workflow tools (and more) and use them to help create more efficiently. The collection is constantly growing, too.

CodeStream

CodeStream might be the new-world workflow tool for web designers and developers. It is made for remote teams to review code right inside your IDE without breaking from development flow. You can post and review changes and comments are all independent of the code itself, even though they link to it.

Litur

Litur is a color management app for iOS. Use it to find and collect color swatches, create custom palettes, and even check color combinations against accessibility standards. The app can even generate color codes for you from swatches you find from a photo or image upload or create. The app works on mobile and desktop Mac devices and is a paid app.

Editor X

Editor X, which is still in beta, is a website building tool that combines advanced design and prototyping capabilities with secure web hosting and integrated business solutions. Go from an idea straight to production in a highly intuitive design workspace. The best feature might be exact design precision tools.

Grid Cheatsheet

Grid Cheatsheet is a visual and code-based set of “cheats” based on the W3C CSS Grid Specifications. What’s nice is it makes these guidelines easier to understand and use if reading through them makes you a little uneasy.

Tutorialist

Tutorialist brings together some of the best development tutorials on the web. All of the tutorials are free videos available on YouTube, and this project collects them all in one place.

Pure CSS Halftone Portrait from JPG

Pure CSS Halftone Portrait from JPG is a beautiful pen from Ana Tudor that shows how to change the visual representation of an image. The examples are brilliant and in true halftone fashion. The code snippet works with color, or black and white images as well.

VoiceText for Slack

VoiceText for Slack is another work from home productivity tool. Integrate it with Slack and send messages with text that’s transcribed right in your channels. It’s a free integration and supports 18 languages.

Feature Peek

Feature Peek is a developer tool that helps you get frontend staging environments on demand and gather team feedback earlier in the development process. It’s made for use with GitHub and works with a variety of other tools as well.

Formbutton

Formbutton is a simple and customizable pop-up form. (And we all know websites have plenty of them right now.) It connects to other services you already use, such as Google Sheets and MailChimp, and is simple to set up.

Blocksy Theme

Blocksy is a WordPress theme that’s made for non-coders. It’s a zippy and highly visual theme made for Gutenberg. It works with other builders and allows the user to customize pretty much everything visually. (There’s even a dark mode.) The theme is packed with tools and options and is a free download.

Oh My Startup Illustrations

Oh My Startup Illustrations is a set of vector illustrations in several categories featuring a popular style on many projects. Use the characters and scenes to create a semi-custom story for your startup project.

1mb

1mb is a code editor and host where you can create a static website with a custom domain and SSL included. The editor works in-browser and everything is saved in the cloud.

Linear

Linear is an issue tracking Mac app for teams. It’s designed to help streamline software projects, sprints, and tasks, and can integrate with standard tools such as Github, Figma, and Slack.

Hosting Checker

Hosting Checker solves a common issue – a client wants you to work on their website, but has no idea who hosts it. Hosting Checker shows the user hosting provider and IP address the website uses, along with where its server computers are located and the host’s contact details. It also claims to be 82% faster than other similar tools.

Spike

Spike alerts you to website incidents before customers. Create alerts and get a phone call, text message, email, or Slack notification right away. The tool provides unlimited alerts and integrations to you can stay on top of issues before they become real problems.

Magnus UI

Magnus UI is a framework that helps you building consistent user interfaces in React. It comes with plenty of components ready to use and you can customize the theme.

SpreadSimple

SpreadSimple uses data in Google Sheets to create styled websites with features such as filtering, search, sorting, cart, order collection via forms, and much more. Update the sheet and instantly see changes on the website.

WebP vs. JPEG

Google is starting to suggest using it’s WebP image format to decrease load times, because of the lighter file size. But is WebP better than the traditional JPEG? Developer Johannes Siipola tested the file types at different sizes to answer the question. The answer is a bit complicated, but sometimes it might be better; read the full analysis for more.

Oh Dear

Oh Dear is a website monitoring tool that can help you keep a check on websites. Monitor uptime, SSL certificates, broken links, and more with notifications that come right to you if there’s an issue.

Airconnect

Airconnect is a Zoom video conferencing alternative that you can use for your brand with a custom header, colors, and portal for clients. The tool includes video calling as well as the ability for customers to access their data and automate your onboarding process.

Free Faces

Free Faces is a curated collection of free typefaces that you can browse and use in projects. Search by type style with visual results that include a download link.

All the Roll

All the Roll is a fun novelty font for just the right type of project. It includes 167 characters with swash characters that can be added before or after certain letters.

Backrush

Backrush is a handwriting-style typeface with easy strokes and a pen-like feel. It includes thicker letterforms with nice swashes and a full character set.

Thuner

Thuner is a slab display font with interesting quirks. It’s made for larger than life designs. It includes a full uppercase character set and numerals.

Source

Categories: Designing, Others Tags:

How To Create A Custom React Hook To Fetch And Cache Data

July 13th, 2020 No comments
Smashing Editorial

How To Create A Custom React Hook To Fetch And Cache Data

How To Create A Custom React Hook To Fetch And Cache Data

Ademola Adegbuyi

2020-07-13T09:00:00+00:00
2020-07-13T17:34:04+00:00

If you are a newbie to React Hooks, you can start by checking the official documentation to get a grasp of it. After that, I’d recommend reading Shedrack Akintayo’s “Getting Started With React Hooks API”. To ensure you’re following along, there is also an article written by Adeneye David Abiodun that covers best practices with React Hooks which I’m sure will prove to be useful to you.

Throughout this article, we’ll be making use of Hacker News Search API to build a custom hook which we can use to fetch data. While this tutorial will cover the Hacker News Search API, we’ll have the hook work in a way that it will return response from any valid API link we pass to it.

Best Practices With React

React is a fantastic JavaScript library for building rich user interfaces. It provides a great component abstraction for organizing your interfaces into well-functioning code, and there’s just about anything you can use it for. articles on React ?

Fetching Data In A React Component

Before React hooks, it was conventional to fetch initial data in the componentDidMount() lifecycle method, and data based on prop or state changes in componentDidUpdate() lifecycle method.

Here’s how it works:

componentDidMount() {
  const fetchData = async () => {
    const response = await fetch(
      `https://hn.algolia.com/api/v1/search?query=JavaScript`
    );
    const data = await response.json();
    this.setState({ data });
  };
  
  fetchData();
}


componentDidUpdate(previousProps, previousState) {
    if (previousState.query !== this.state.query) {
      const fetchData = async () => {
        const response = await fetch(
          `https://hn.algolia.com/api/v1/search?query=${this.state.query}`
        );
        const data = await response.json();
        this.setState({ data });
      };

      fetchData();
    }
  }

The componentDidMount lifecycle method gets invoked as soon as the component gets mounted, and when that is done, what we did was to make a request to search for “JavaScript” via the Hacker News API and update the state based on the response.

The componentDidUpdate lifecycle method, on the other hand, gets invoked when there’s a change in the component. We compared the previous query in the state with the current query to prevent the method from getting invoked every time we set “data” in state. One thing we get from using hooks is to combine both lifecycle methods in a cleaner way — meaning that we won’t need to have two lifecycle methods for when the component mounts and when it updates.

Fetching Data With useEffect Hook

The useEffect hook gets invoked as soon as the component is mounted. If we need the hook to rerun based on some prop or state changes, we’ll need to pass them to the dependency array (which is the second argument of the useEffect hook).

Let’s explore how to fetch data with hooks:

import { useState, useEffect } from 'react';

const [status, setStatus] = useState('idle');
const [query, setQuery] = useState('');
const [data, setData] = useState([]);

useEffect(() => {
    if (!query) return;

    const fetchData = async () => {
        setStatus('fetching');
        const response = await fetch(
            `https://hn.algolia.com/api/v1/search?query=${query}`
        );
        const data = await response.json();
        setData(data.hits);
        setStatus('fetched');
    };

    fetchData();
}, [query]);

In the example above, we passed query as a dependency to our useEffect hook. By doing that, we’re telling useEffect to track query changes. If the previous query value isn’t the same as the current value, the useEffect get invoked again.

With that said, we’re also setting several status on the component as needed, as this will better convey some message to the screen based on some finite states status. In the idle state, we could let users know that they could make use of the search box to get started. In the fetching state, we could show a spinner. And, in the fetched state, we’ll render the data.

It’s important to set the data before you attempt to set status to fetched so that you can prevent a flicker which occurs as a result of the data being empty while you’re setting the fetched status.

Creating A Custom Hook

“A custom hook is a JavaScript function whose name starts with ‘use’ and that may call other Hooks.”

React Docs

That’s really what it is, and along with a JavaScript function, it allows you to reuse some piece of code in several parts of your app.

The definition from the React Docs has given it away but let’s see how it works in practice with a counter custom hook:

const useCounter = (initialState = 0) => {
      const [count, setCount] = useState(initialState);
      const add = () => setCount(count + 1);
      const subtract = () => setCount(count - 1);
      return { count, add, subtract };
};

Here, we have a regular function where we take in an optional argument, set the value to our state, as well as add the add and the subtract methods that could be used to update it.

Everywhere in our app where we need a counter, we can call useCounter like a regular function and pass an initialState so we know where to start counting from. When we don’t have an initial state, we default to 0.

Here’s how it works in practice:

import { useCounter } from './customHookPath';

const { count, add, subtract } = useCounter(100);

eventHandler(() => {
  add(); // or subtract();
});

What we did here was to import our custom hook from the file we declared it in, so we could make use of it in our app. We set its initial state to 100, so whenever we call add(), it increases count by 1, and whenever we call subtract(), it decreases count by 1.

Creating useFetch Hook

Now that we’ve learned how to create a simple custom hook, let’s extract our logic to fetch data into a custom hook.

const useFetch = (query) => {
    const [status, setStatus] = useState('idle');
    const [data, setData] = useState([]);

    useEffect(() => {
        if (!query) return;

        const fetchData = async () => {
            setStatus('fetching');
            const response = await fetch(
                `https://hn.algolia.com/api/v1/search?query=${query}`
            );
            const data = await response.json();
            setData(data.hits);
            setStatus('fetched');
        };

        fetchData();
    }, [query]);

    return { status, data };
};

It’s pretty much the same thing we did above with the exception of it being a function that takes in query and returns status and data. And, that’s a useFetch hook that we could use in several components in our React application.

This works, but the problem with this implementation now is, it’s specific to Hacker News so we might just call it useHackerNews. What we intend to do is, to create a useFetch hook that can be used to call any URL. Let’s revamp it to take in a URL instead!

const useFetch = (url) => {
    const [status, setStatus] = useState('idle');
    const [data, setData] = useState([]);

    useEffect(() => {
        if (!url) return;
        const fetchData = async () => {
            setStatus('fetching');
            const response = await fetch(url);
            const data = await response.json();
            setData(data);
            setStatus('fetched');
        };

        fetchData();
    }, [url]);

    return { status, data };
};

Now, our useFetch hook is generic and we can use it as we want in our various components.

Here’s one way of consuming it:

const [query, setQuery] = useState('');

const url = query && `https://hn.algolia.com/api/v1/search?query=${query}`;
const { status, data } = useFetch(url);

In this case, if the value of query is truthy, we go ahead to set the URL and if it’s not, we’re fine with passing undefined as it’d get handled in our hook. The effect will attempt to run once, regardless.

Memoizing Fetched Data

Memoization is a technique we would use to make sure that we don’t hit the hackernews endpoint if we have made some kind of request to fetch it at some initial phase. Storing the result of expensive fetch calls will save the users some load time, therefore, increasing overall performance.

Note: For more context, you could check out Wikipedia’s explanation on Memoization.

Let’s explore how we could do that!

const cache = {};

const useFetch = (url) => {
    const [status, setStatus] = useState('idle');
    const [data, setData] = useState([]);

    useEffect(() => {
        if (!url) return;

        const fetchData = async () => {
            setStatus('fetching');
            if (cache[url]) {
                const data = cache[url];
                setData(data);
                setStatus('fetched');
            } else {
                const response = await fetch(url);
                const data = await response.json();
                cache[url] = data; // set response in cache;
                setData(data);
                setStatus('fetched');
            }
        };

        fetchData();
    }, [url]);

    return { status, data };
};

Here, we’re mapping URLs to their data. So, if we make a request to fetch some existing data, we set the data from our local cache, else, we go ahead to make the request and set the result in the cache. This ensures we do not make an API call when we have the data available to us locally. We’ll also notice that we’re killing off the effect if the URL is falsy, so it makes sure we don’t proceed to fetch data that doesn’t exist. We can’t do it before the useEffect hook as that will go against one of the rules of hooks, which is to always call hooks at the top level.

Declaring cache in a different scope works but it makes our hook go against the principle of a pure function. Besides, we also want to make sure that React helps in cleaning up our mess when we no longer want to make use of the component. We’ll explore useRef to help us in achieving that.

Memoizing Data With useRef

useRef is like a box that can hold a mutable value in its .current property.”

React Docs

With useRef, we can set and retrieve mutable values at ease and its value persists throughout the component’s lifecycle.

Let’s replace our cache implementation with some useRef magic!

const useFetch = (url) => {
    const cache = useRef({});
    const [status, setStatus] = useState('idle');
    const [data, setData] = useState([]);

    useEffect(() => {
        if (!url) return;
        const fetchData = async () => {
            setStatus('fetching');
            if (cache.current[url]) {
                const data = cache.current[url];
                setData(data);
                setStatus('fetched');
            } else {
                const response = await fetch(url);
                const data = await response.json();
                cache.current[url] = data; // set response in cache;
                setData(data);
                setStatus('fetched');
            }
        };

        fetchData();
    }, [url]);

    return { status, data };
};

Here, our cache is now in our useFetch hook with an empty object as an initial value.

Wrapping Up

Well, I did state that setting the data before setting the fetched status was a good idea, but there are two potential problems we could have with that, too:

  1. Our unit test could fail as a result of the data array not being empty while we’re in the fetching state. React could actually batch state changes but it can’t do that if it’s triggered asynchronously;
  2. Our app re-renders more than it should.

Let’s do a final clean-up to our useFetch hook.,We’re going to start by switching our useStates to a useReducer. Let’s see how that works!

const initialState = {
    status: 'idle',
    error: null,
    data: [],
};

const [state, dispatch] = useReducer((state, action) => {
    switch (action.type) {
        case 'FETCHING':
            return { ...initialState, status: 'fetching' };
        case 'FETCHED':
            return { ...initialState, status: 'fetched', data: action.payload };
        case 'FETCH_ERROR':
            return { ...initialState, status: 'error', error: action.payload };
        default:
            return state;
    }
}, initialState);

Here, we added an initial state which is the initial value we passed to each of our individual useStates. In our useReducer, we check what type of action we want to perform, and set the appropriate values to state based on that.

This resolves the two problems we discussed earlier, as we now get to set the status and data at the same time in order to help prevent impossible states and unnecessary re-renders.

There’s just one more thing left: cleaning up our side effect. Fetch implements the Promise API, in the sense that it could be resolved or rejected. If our hook tries to make an update while the component has unmounted because of some Promise just got resolved, React would return Can't perform a React state update on an unmounted component.

Let’s see how we can fix that with useEffect clean-up!

useEffect(() => {
    let cancelRequest = false;
    if (!url) return;

    const fetchData = async () => {
        dispatch({ type: 'FETCHING' });
        if (cache.current[url]) {
            const data = cache.current[url];
            dispatch({ type: 'FETCHED', payload: data });
        } else {
            try {
                const response = await fetch(url);
                const data = await response.json();
                cache.current[url] = data;
                if (cancelRequest) return;
                dispatch({ type: 'FETCHED', payload: data });
            } catch (error) {
                if (cancelRequest) return;
                dispatch({ type: 'FETCH_ERROR', payload: error.message });
            }
        }
    };

    fetchData();

    return function cleanup() {
        cancelRequest = true;
    };
}, [url]);

Here, we set cancelRequest to true after having defined it inside the effect. So, before we attempt to make state changes, we first confirm if the component has been unmounted. If it has been unmounted, we skip updating the state and if it hasn’t been unmounted, we update the state. This will resolve the React state update error, and also prevent race conditions in our components.

Conclusion

We’ve explored several hooks concepts to help fetch and cache data in our components. We also went through cleaning up our useEffect hook which helps prevent a good number of problems in our app.

If you have any questions, please feel free to drop them in the comments section below!

References

(ks, ra, yk, il)

Categories: Others Tags:

Popular Design News of the Week: July6, 2020 – July 12, 2020

July 12th, 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.

Lunchbox by Sandwich

Overview of the Best Cross Browser Testing Tools

Design Better Buttons

Pros and Cons of Horizontal Vs. Vertical Scaling

Free Illustrations – Free to Use Illustrations & Vectors

Plumpicons – UI Icons with Character

4 Ways to Improve your Latest Product’s Landing Page to Guarantee Conversion

The Design Systems Between Us

Do You Need a Landing Page? Some Useful Tips

25 Creative Logo Designs for Inspiration

The Comeback of Fun in Visual Design

Zettlr – A Markdown Editor

A Terrible, Horrible, No-Good, Bad Day at Slack

Anima is Now Available for Figma

Why Every Developer Should Know Multiple Programming Languages

A Freelancer’s Guide to Crafting Effective Project Proposals

The Guide to Design

10 Ways to Explain the Job of a Graphic Designer to a Child

Art of Contrast: 40+ Expressive Illustrations

How to Turn Negative Feedback into Design Gold

Creative Packaging Design Ideas: 20 Projects for your Inspiration

1-Line Layouts – 10 Modern CSS Layout and Sizing Techniques

The Cicada Principle, Revisited with CSS Variables

Battle of the Interface Design Tools

Best Time of Year to Apply for UI/UX and Product Designer Jobs

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

Source

Categories: Designing, Others Tags:

An Eleventy Starter with Tailwind CSS and Alpine.js

July 10th, 2020 No comments

When I decided to try to base my current personal website on Eleventy, I didn’t want to reinvent the wheel: I tested all the Eleventy starters built with Tailwind CSS that I could find in Starter Projects from the documentation.

Many of the starters seemed to integrate Tailwind CSS in a contrived way. Also, some of them seemed to assume that no one updates Tailwind’s configuration on the fly while working on a website. That’s why I integrated Eleventy with Tailwind CSS and Alpine.js myself. I have reason to believe that you’ll like the simplicity of my solution.

Good design is as little design as possible.

—Dieter Rams, 10 Principles for Good Design

If you’re uninterested in the details, feel free to grab my starter and jump right in.

Getting started

I’m going to assume you have a general understanding of Tailwind CSS, HTML, JavaScript, Nunjucks, the command line, and npm.

Let’s start by with a new a folder, then cd to it in the command line, and initialize it with a package.json file:

npm init -y

Now we can install Eleventy and Tailwind CSS. We’ll throw in PostCSS as well:

npm install --save-dev @11ty/eleventy tailwindcss postcss-cli

We need to create a page to test whether we’ve successfully set things up. In a real use case, our pages will use templates, so we’ll do that here as well. That’s where Nunjucks fits into the mix, serving as a templating engine.

Let’s make a new file called index.njk in the project folder. We’ll designate it as the homepage:

{% extends "_includes/default.njk" %}


{% block title %}It does work{% endblock %}


{% block content %}
  <div class="fixed inset-0 flex justify-center items-center">
    <div>
      <span class="text-change">Good design</span><br/>
      <span class="change">is<br/>as little design<br/>as possible</span>
    </div>
  </div>
{% endblock %}

Basic templating

Now let’s create a new folder in the project folder called _includes (and yes, the folder name matters). Inside this new folder, we’ll create a file called default.njk that we’ll use as the default template for our layout. We’ll keep things simple with a basic HTML boilerplate:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>
      {% block title %}Does it work?{% endblock %}
    </title>
    <meta charset="UTF-8"/>
    {% if description %}
      <meta name="description" content="{{description}}"/>
    {% endif %}
    <meta http-equiv="x-ua-compatible" content="ie=edge"/>
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, viewport-fit=cover"/>
    <link rel="stylesheet" href="/style.css?v={% version %}"/>
    {% block head %}{% endblock %}
  </head>
  <body>
    {% block content %}
      {{ content | safe }}
    {% endblock %}
  </body>
</html>

Configuring Tailwind CSS

Let’s take care of a test for Tailwind CSS in as few moves as possible. First, create a new subfolder called styles and a file in it called tailwind.config.js:

module.exports = {
  theme: {
    colors: {
      change: "transparent"
    }
  },
  variants: {},
  plugins: [],
}

Then, create a file called tailwind.css in that same styles folder:

/* purgecss start ignore */
@tailwind base;
/* purgecss end ignore */


.change {
  color: transparent;
}


/* purgecss start ignore */
@tailwind components;
/* purgecss end ignore */


@tailwind utilities;

We’re done with the styles folder for now. What we do need is a configuration file that tells PostCSS to use Tailwind CSS, which we can get by creating a new file in the root directory of the project folder called postcss.config.js. Here’s how we require Tailwind CSS and its configuration file with PostCSS:

module.exports = {
  plugins: [
    require(`tailwindcss`)(`./styles/tailwind.config.js`)
  ],
};

Starting and building the project

Now let’s create another new file in the same root directory called .gitignore. This will allow us to define what files to skip when committing the project to a repo, like on GitHub:

_site/
_tmp/
.DS_Store
node_modules/
package-lock.json

Next, is another new file, this time one that tells Eleventy what it can ignore, called .eleventyignore. It only needs one line:

node_modules

OK, now we will create a file called .eleventy.js (note the leading dot!) that basically configures Eleventy, telling it what files to watch and where to save its work:

module.exports = function (eleventyConfig) {
  eleventyConfig.setUseGitIgnore(false);


  eleventyConfig.addWatchTarget("./_tmp/style.css");


  eleventyConfig.addPassthroughCopy({ "./_tmp/style.css": "./style.css" });


  eleventyConfig.addShortcode("version", function () {
    return String(Date.now());
  });
};

We can now update the package.json file with all of the scripts we need to start and build the site during development. The dependencies should already be there from the initial setup.

{
  "scripts": {
    "start": "eleventy --serve & postcss styles/tailwind.css --o _tmp/style.css --watch",
    "build": "ELEVENTY_PRODUCTION=true eleventy & ELEVENTY_PRODUCTION=true postcss styles/tailwind.css --o _site/style.css"
  },
  "devDependencies": {
    "@11ty/eleventy": "^0.11.0",
    "postcss-cli": "^7.1.0",
    "tailwindcss": "^1.4.6"
  }
}

Hey, great job! We made it. Build the project to generate the initial CSS — this step is only required the very first time we set up. From the command line:

npm run build

And — drumroll, please — let’s officially start the site:

npm run start

Open the page http://localhost:8080 in your browser. It’s not gonna look like much, but check out the page title in the browser tab:

It does work!

We can still do a little more checking to make sure everything’s good. Open up /styles/tailwind.config.js and change the transparent color value to something else, say black. Tailwind’s configuration should reload, along with the page in your browser.

Don’t lose sight of your browser and edit /styles/tailwind.css by changing transparent to black again. Your CSS file should reload and refresh in your browser.

Now we can work nicely with Eleventy and Tailwind CSS!

Optimizing the output

At this point, Tailwind CSS works with Eleventy, but the CSS file is huge. The generated HTML isn’t perfect either because it contains stuff like redundant newline characters. Let’s clean it up:

npm install --save-dev @fullhuman/postcss-purgecss postcss-clean html-minifier

Open up postcss.config.js and replace what’s in there with this:

module.exports = {
  plugins: [
    require(`tailwindcss`)(`./styles/tailwind.config.js`),
    require(`autoprefixer`),
    ...(process.env.ELEVENTY_PRODUCTION
      ? [
          require(`postcss-clean`),
          require(`@fullhuman/postcss-purgecss`)({
            content: ["_site/**/*.html"],
            defaultExtractor: (content) =>
              content.match(/[w-/:]+(?<!:)/g) || [],
            whitelist: [],
            whitelistPatterns: [/body/, /headroom/, /ril/],
          }),
        ]
      : []),
  ],
};

In the future, in the process of creating your website, if something looks wrong after you build the project and you have the impression that fragments of CSS are missing, add “ignored” class names to the whitelist in the file above.

Add the following line to the beginning of the .eleventy.js file:

const htmlmin = require("html-minifier");

We also need to configure htmlmin in .eleventy.js as well:

eleventyConfig.addTransform("htmlmin", function (content, outputPath) {
    if (
      process.env.ELEVENTY_PRODUCTION &&
      outputPath &&
      outputPath.endsWith(".html")
    ) {
      let minified = htmlmin.minify(content, {
        useShortDoctype: true,
        removeComments: true,
        collapseWhitespace: true,
      });
      return minified;
    }


    return content;
});

We’re using a transform here which is an Eleventy thing. Transforms can modify a template’s output. At this point, .eleventy.js should look like this:

const htmlmin = require("html-minifier");


module.exports = function (eleventyConfig) {
  eleventyConfig.setUseGitIgnore(false);


  eleventyConfig.addWatchTarget("./_tmp/style.css");


  eleventyConfig.addPassthroughCopy({ "./_tmp/style.css": "./style.css" });


  eleventyConfig.addShortcode("version", function () {
    return String(Date.now());
  });


  eleventyConfig.addTransform("htmlmin", function (content, outputPath) {
    if (
      process.env.ELEVENTY_PRODUCTION &&
      outputPath &&
      outputPath.endsWith(".html")
    ) {
      let minified = htmlmin.minify(content, {
        useShortDoctype: true,
        removeComments: true,
        collapseWhitespace: true,
      });
      return minified;
    }


    return content;
  });
};

Alright, let’s run npm run start once again. You’ll see that nothing has changed and that’s because optimization only happens during build. So, instead, let’s try npm run build and then look at the _site folder. There shouldn’t be a single unnecessary character in the index.html file. The same goes for the style.css file.

A project built like this is now ready to deploy. Good job! ?

Integrating Alpine.js

I decided to switch to Eleventy from Gatsby.js because it just felt like too much JavaScript to me. I’m more into the reasonable dose of vanilla JavaScript mixed with Alpine.js. We won’t get into the specifics of Alpine.js here, but it’s worth checking out Hugo DiFrancesco’s primer because it’s a perfect starting point.

Here’s how we can install it to our project from the command line:

npm install --save-dev alpinejs

Now we need to update .eleventy.js with this to the function that passes things through Alpine.js:

eleventyConfig.addPassthroughCopy({
  "./node_modules/alpinejs/dist/alpine.js": "./js/alpine.js",
});

Lastly, we’ll open up _includes/default.njk and add Alpine.js right before the closing tag:

<script src="/js/alpine.js?v={% version %}"></script>

We can check if Alpine is working by adding this to index.njk:

{% extends "_includes/default.njk" %}


{% block title %}It does work{% endblock %}


{% block content %}
  <div class="fixed inset-0 flex justify-center items-center">
    <div>
      <span class="text-change">Good design</span><br/>
      <span class="change">is<br/>as little design<br/>as possible</span><br/>
      <span x-data="{message:'🤖 Hello World 🤓'}" x-text="message"></span>
    </div>
  </div>
{% endblock %}

Launch the project:

npm run start

If Alpine.js works, you’ll see “Hello World” in your browser. Congratulations, times two! ??


I hope you can see how quick it can be to set up an Eleventy project, including integrations with Nunjucks for templating, Tailwind for styles and Alpine.js for scripts. I know working with new tech can be overwhelming and even confusing, so feel free to email me at csstricks@gregwolanski.com if you have problems starting up or have an idea for how to simplify this even further.

The post An Eleventy Starter with Tailwind CSS and Alpine.js appeared first on CSS-Tricks.

Categories: Designing, Others Tags:

We need more inclusive web performance metrics

July 10th, 2020 No comments

Scott Jehl argues that performance metrics such as First Contentful Paint and Largest Contentful Paint don’t really capture the full picture of everyone’s experience with websites:

These metrics are often touted as measures of usability or meaning, but they are not necessarily meaningful for everyone. In particular, users relying on assistive technology (such as a screenreader) may not perceive steps in the page loading process until after the DOM is complete, or even later depending on how JavaScript may block that process. Also, a page may not be usable to A.T. until it becomes fully interactive, since many applications often deliver accessible interactivity via external JavaScript

Scott then jots down some thoughts on how we might do that. I think this is always so very useful to keep in mind: what we experience on our site, and what we measure too, might not be the full picture.

Direct Link to ArticlePermalink

The post We need more inclusive web performance metrics appeared first on CSS-Tricks.

Categories: Designing, Others Tags:

Bridging The Gap Between Writers And Content Uploaders

July 10th, 2020 No comments

A good writer doesn’t automatically mean a fully-fleshed content machine.

Some may be crazy good reviewers… but not that much of a copywriter to write your article’s description.

Some may be amazing with breaking up data into digestible long-form pieces… but won’t know enough about your CMS to properly upload their latest piece.

It’s understandable.

But that creates a gap between the person writing the content, and the person that’s supposed to upload it.

So let’s bridge that gap.

How Do You Upload Content?

Ok, we know you know. If you’re here, you’ve probably been uploading content for a while. If you think you have the right recipe, just skip this part. For the rest of us, I think it’s important to remember what needs to be taken into account.

So first, you have to worry about…

Formatting

If you use WordPress, most of the job is done after a quick set-up in the Customize tab.

But depending on the document editing software used (Microsoft Office, gDrive, etc) bullet lists and images might not always translate into clean paragraphs.

In that case, the content uploader will have to move around and remove some spaces.

It doesn’t sound like a lot, but if you’re uploading 30 articles at a time, it might take a while. Not to mention, if you’re not using WordPress, who knows what compatibility issues may arise.

And that’s the first gap between writers and uploaders.

But that’s not all.

Multimedia Content

Depending on your site’s formatting, you’ll have different naming and posting conventions for multimedia content.

Even quotes or code parts might fall in this category.

If your writer isn’t privy to that information, you’ll have to work a lot when uploading content.

And that’s another area where your writer and content uploader might not see eye to eye. While for the writer, it would only take a few seconds to name a screenshot accordingly, the content uploader will have to plow through 30 or more images and rename all of them.

That’s time lost.

SEO

No matter where you’re set-up, meta-descriptions, target keywords and links will have to be set-up before you publish a new piece.

And if your writers didn’t sign up for that, or if they just don’t know how to do it, uploading will take considerably longer.

Especially since uploaders usually give the piece…

One Last Read

Yes, this article is about the person uploading an article.

And you may have different people hired as editors, so in theory, uploading should have no editing involved.

But that’s not a norm. Quite the contrary.

If you’re a one-man show for the most part, or if you can’t afford paying a person to upload and schedule your content, you’re wearing more hats.

And so you add all of that time spent on formatting, SEO and multimedia content to the actual editing of the article.

Which includes that one last read before hitting publish.

And if you’re publishing long-form content, all that process might take a while.

So The Gap…

Is real.

If you don’t have a well-oiled editorial machine, those problems will arise and inconvenience your team.

Luckily, you can bridge that gap.

Bridging The Gap

Can only be done gradually.

If you want to change your SEO requirements for writers, ease it into your briefs after you discuss it with them.

And definitely use tools to help make the change easier.

Other than that, here we go.

Option #1 – Have Your Writers Upload The Content

Seems pretty obvious, but that doesn’t mean it’s easy. Especially if you work with low-skilled, low-paid writers that are just starting out.

Plus, you might not want to give new team members control over your CMS.

So if this isn’t for you, skip to Option 2.

But if you are considering letting your writers upload the content they produce, you need to take it slow. Don’t just pass on the login credentials and hope for the best.

Start out by having them assume more responsibilities. Let them take charge of the SEO research for their articles for example.

Speaking of, that shouldn’t be hard if you use ahrefs and the Surfer Content Editor. It’s what we use, and it works wonders in bridging the gap between writers and content uploaders.

Take the same stance with formatting, writing short descriptions for posts, or even adding multimedia content.

Have your writers come up with the meta-description for the articles they’re writing.

In the short run, this will make it easier for content uploaders to do their job.

In the long run, this will teach writers everything they need to upload content themselves.

However, regardless of how experienced your writers are, or how well they did in the “trial”, try to hold their hand during the first one or two pieces of content uploaded. This might even be a good time to upskill them overall.

If you need some help training your writers, check out Noupe’s tips for generating content.

Oh and, definitely show them how to use your CMS beforehand.

Option #2 Optimize The Workflow

If you don’t feel comfortable conceding a lot of control to your writers, you can try the first step of Option 1: have them assume more responsibilities over time.

But there are plenty of ways to do that.

So let’s talk about each aspect of content uploading.

Better Formatting

Depending on your CMS and your writer’s document editing software, you might have different needs with formatting.

If you don’t want to stop and look for minute details, you can have your writers use Markdown.

It’s an adapted type of HTML writing, and it will get pasted the same everywhere. If you want to go that route, we recommend using Typora to create the content in a decent UX.

And we also advise some patience. It will take a while for your writers to get accustomed to the tool.

Better Multimedia Content

If you create custom multimedia content – like images with a specific width and color pallete, or tables formatted in a certain way – just show your writers how to do that.

You don’t need to be a designer to use screenshoting software.

And beautiful tables aren’t hard to create.

On top, if you have a naming convention, put it in the briefs of articles.

Regardless of how well your writers will adapt to new changes, this is bound to bridge the gap at least a little bit.

Lastly, make sure you read our tutorial on how to use design to amplify your brand’s content marketing.

Better SEO

At Authority Hacker, we trust our writers enough to let them do their own LSI research, and use the target keyword as recommended.

But they don’t have a ton of work to do..

We plan our content strategy with ahrefs, and then we use the Surfer Content Editor to make sure our writers can implement the right keywords in their work.

It works wonders to bridge the gap, and its data is reliable too.

Smoother Editing

Good writers know how to edit their own work.

If that’s not true for your writers, you might want to focus on improving your editorial process. Buy a Grammarly extension to help your writers with the odd grammar mistake, and teach them how to write better copy.

All of these will help bridge the gap between writers and content uploaders.

And For Our Final Tip

Be proactive, pay attention to your team, and adapt.

We explored some solutions, but to truly breach the gap, you need to adapt to your team’s needs. If you’re running an affiliate website for example, you might need writers to be able to make room for affiliate links naturally.

If you’re looking for inspiration, we actually have a giant list of some of the most successful affiliate websites examples.

Talk to your content uploaders. Talk to your writers. Take the time to understand where the gap is coming from.

Know that and you’ll be able to adapt all of this to your site.


Photo by Austin Distel on Unsplash

Categories: Others Tags:

5 Popular UI Design Trends Everyone Must Know

July 10th, 2020 No comments

The user interface is not a new term for any of us, rather we should declare it as an integral part of our daily lives. Knowingly or unknowingly we are continuously being bombarded with the beauty of UI designs. When we break down the term User Interface, we discover the way through which users can interact with any sort of digital platform like apps, websites, etc.

For the people who stick to the Internet to accomplish their day to day operations, the importance of effective interaction is unmatchable. The entire world values the importance of design and usability. It is very difficult to be sure of something in this fast-paced era, but one thing we can guarantee is that the Internet is here to stay. So if your business is dependent on it, it’s recommended to provide a platform that aims towards convenient interaction. One must always remember that any device will allow the user to interact, but the success lies in providing excellence.

A misplaced button or poor navigation, the cause of losing your audience can vary; it all depends on User Interface Design. We know that the competition in the market is cutting edge, and if the audience is unable to grasp the services you are offering, they will switch to your closest competitor. Hence, for all the designers it is a must to know what the audience is craving for. The path to attaining unmatchable value for your users is through implementing the best-suited UI design that is trending globally.

So here in this blog, we will learn about the top trending UI Designs that can help designers to improve the platform they are working on. So shall we begin?

Here are the most inspiring, creative, and progressive user interface designs one must know. Take a good look to develop a clear perspective of what you want.

1. Pastel Backgrounds

In a short time span of a few years, this trend started drawing worldwide attention. From websites to social media, everyone is catching up to stand out. Pastels are the colors created when any normal color is mixed with white. This softens the look of the color and makes it pale while maintaining the personality. They are inspiring the designers to bring more and more elegance in the user interface.

This scheme is allowing the applications and websites to oomph up their sophistication game. They play a huge role in uncluttering the UI. Here are the few qualities of pastel backgrounds that everyone loves.

  • Non-intrusive
  • Sophisticated
  • Delightful
  • Light-weight
  • Fresh
  • Modern

For any designer using this scheme will bring a lot of joy. But have you ever used it in your visual creations? Let us know!

2. Neumorphism or Neo-skeuomorphism

It is a new technique that provides a minimal way to design with a soft plastic look. This trend is challenging the UI designers and front-end developers all over the world. It brings us a new iteration of a style of designing frames, elements, screens, and much more. This is way different from conventional designs. For example, by following the traditional pattern of design, the buttons have a way to stand out. With clear borders, they have the potential to get noticed very easily. But in metamorphism, the border smoothly blends in with the background, making it difficult to use.

Although the world stands divided on this trend, it carries the ability to bring out the most elegant solutions. It provides a treat to the fun-loving and extraordinary set of designers. Let us know, in the comment section, if you have ever had a chance to explore it!

3. Geometric & Abstract shapes

Just when you think that there is nothing more left to explore in digital designing, something new starts turning heads. Valuable and effective ideas go on to become trends. For example abstract shapes. Web designers like to explore geometric design elements for enhancing the look and feel of the platform. They allow designers to organize content by producing clarity. They are mostly used for UI elements and backgrounds. With the use of abstract shapes, the UI becomes more playful.

Designers can showcase their skills by trying a variety of colors and gradients, experiment with boundaries and shapes, etc. To make it shine, make sure to add an element of simplicity and let your imagination flow. There are a variety of types in abstract shapes, some of them include-

  • Geometric style
  • Free-form shapes
  • Organic
  • Natural

They allow the creators to develop a functional style and keep a close eye on it to grab attention.

4. Soft gradients

Gradients have the potential to catch your eye. Cards, buttons, graphs, or any other UI elements are living proof that gradients are not vanishing any time soon. With the use of gradients, designers can access their creative freedom, as it paves the way for infinite opportunities. With this trend, designers can create memorable visual designs. The atrocities face during flat design can be easily solved by soft gradients as it provides depth and dimension in the user interface. This trend’s versatility allows the creators to make bold statements and helps them to make the designs more intense.

5. Dark mode

This trend is a blessing for all the night howlers, as it makes the digital platforms more accessible in the night. It is basically a color-inverted form of the UI. It is a must that the creators keep a check on typography and color contrast while developing the dark mode.

This trend became popular with the expansion of the internet and digital platforms. As the users started utilizing their time at the night for swiping through their favorite websites and apps, it created a need to switch to dark mode.

These are the five most popular UI design trends that everyone must know. But that is not all, because the pandora of creativity keeps on exploring. If you liked this blog then do let us know in the comment section, but until then stay tuned to this platform for more information.


Photo by eberhard grossgasteiger on Unsplash

Categories: Others Tags:

8 Design Secrets of B2B Vs B2C Websites

July 10th, 2020 No comments

Web design clients come from a wide variety of backgrounds. One day, you’ll be designing a portfolio website for a voiceover artist, the next you’ll be creating a comprehensive ecommerce site for a leading retailer. In an ideal world, you’ll get to a point where you eventually specialize in a niche. However, you’ll need to master both avenues first.

The more time you spend in this industry, the more you’ll learn that every client comes with their own unique requirements and challenges to consider. However, there’s a particularly huge divide between the kind of web design projects you do for B2B clients, and the ones you do for B2C customers.

Both B2B (Business to Business) and B2C (Business to Consumer) websites need to be clear, concise, and aesthetically pleasing. They should always have a strong focus on user experience, and they need to work consistently across devices. However, being aware of the difference between B2B and B2C projects will help you to deliver better results to your customers.

Defining the Differences Between B2B and B2C Sites

Some web design trends remain consistent in any environment.

Whether you’re creating a site for a hairdresser, or a leading SaaS company, you’ll need to deliver responsive design, intuitive navigation, and excellent site security.

Your process is unlikely to differ from B2B to B2C much in terms of project milestones, phases, prototyping and wire-framing. The differences that arise between B2B and B2C projects often come in the approach you take to building certain elements.

Let’s take a closer look at the things you might need to consider:

1. The Target Audience

In any design project, it’s always important to keep the end customer in mind. Knowing your client’s target audience will help you to create both an image and a tone of voice that appeals to the right people.

B2B Websites

With B2B websites, you’ll be speaking to a range of highly-educated individuals who already have a general knowledge of your service. The aim here will be to show the end-user how you can help them achieve better results. For instance, m.io highlights “syncing communication” so you can “effortlessly chat” with your team.

The language and content of the website is all about highlighting the key benefits of the products, and the kind of outcomes that they can deliver. The Nielsen Norman Group reports that there’s often a lot of discussion between decision-makers when they’re checking out a B2B website.

Designers need to work harder at convincing B2B buyers that they’re making the right decision. This is particularly true when you’re selling something like a software subscription that requires a lot of long—term investment.

B2C Websites

On the other hand, while B2B customers make decisions based on logic, information, and well-explained benefits, B2C customers are more influenced by emotion. They want quick solutions to their problems, and the opportunity to purchase from a brand that “understands” them.

Look at the Firebox website, for instance. It instantly highlights an ongoing sale at the top of the homepage, addressing any concerns a customer might have about price. That combined with a quirky layout full of authentic photos and bright colors means that customers are more inclined to take action.

2. The Purpose

Another factor that can vary from B2C to B2B websites, is the motive behind a customer’s purchase. Knowing what’s pushing a target audience to interact with a brand will help you to create a website that appeals to specific goals.

B2B Websites

B2B websites often aim to solve expensive and time-consuming problems for companies. To sell a decision-maker on the validity of a solution, it’s important to thoroughly explain what the solution is, how it works, and how it addressees a specific pain point.

Look at the Zoom website for instance, they don’t just tell people that they offer video conferencing, they address the practical applications of the platform:

B2C Websites

Consumers are a lot easier to appeal to in terms of emotional impact, because many of them come to a website looking to fulfill an urgent need. Because of this, many web designers can take advantage of things like urgency and demand to encourage conversions. For instance, look at this website from TravelZoo. It takes advantage of a customer’s desire to get away:

A B2B website needs to focus on providing information that helps companies to make more confident decisions. What’s more, with B2B sites, decisions are often made by several stakeholders, while B2C sites ask a single person to make a choice. A B2C website needs to address immediate concerns and connect with customers on an emotional level. B2C buyers still want to do their research on products or services, but the turnaround is much quicker, and often requires less information.

3. The Design Elements (Visual Appearance)

Just as the focus of your website design and the audience that you’re creating the experience for can differ from B2B to B2C websites, the visual elements of the design might change too.

B2B Websites

In most cases, B2B websites are all about presenting a highly professional and respectable image. You’ll notice a lot of safe and clear choices when it comes to typography and imagery. It’s unusual to see a B2B website that takes risks with things like illustrations and animations.

Look at the Green Geeks website for instance. Everything is laid out to encourage clarity and understanding. Information is easy to find, and there are no other issues that might distract a customer.

B2C Websites

On the other hand, B2C websites can be a little more daring. With so many different options to choose from, and most customers buying out of a sense of urgency or sudden demand, designers are under pressure to capture attention quick. This means that it’s much more likely to see large pieces of eye-catching imagery on B2C sites, with very little text.

Movement, like slideshows and animations often play more of a role here. Additionally, there’s a good chance that you’ll be able to experiment more aggressively with color. Take a look at the Yotel website, for instance. There’s very little textual information here, but the appeal of the website is conveyed through sliding images:

4. Website Content

The way that information is conveyed on a B2B website is very different to the messages portrayed on a B2C site. Usually, everything from the language, to the amount of content that you use for these projects will differ drastically.

B2B Websites

When designing for a B2B website, you’ll need to be careful with content, as you’ll be speaking to a very mixed audience. If your site caters to different industries, you’ll need to ensure that you show authority, without using too much jargon. Some companies even create different pages on their site for specific customers. The aspin.co.uk website covers the benefits from a company, sale and integration perspective:

Rather than try to talk to all business owners about their differing communication pains, G-Suite anticipates its audience and creates pages for each.

B2C Websites

Alternatively, B2C websites can make things a little simpler. For instance, on glossybox.co.uk, there’s no need to provide a ton of information for different types of shopper, designers can appeal to one audience, i.e. the “beauty addict”:

In both B2B and B2C websites, the aim of the content should always be to answer any questions that the end user might have.

5. CTA Buttons

Call to Action buttons are often a crucial part of the web design journey. However, it’s sometimes difficult to determine where they should be placed, or how many buttons you need.

B2B Websites

Because the decision to buy something won’t always happen immediately with a B2B website, these kinds of sites often use a variety of CTAs. For instance, you might have a “Request a Quote” button at the top of a page, as well as a Sign in button.

On the Klaviyo site, for instance, you can request a demo, sign up or log in:

You can place CTAs lower on the page with B2B websites too, as it’s more likely that your customers will be scrolling through the site to collect more information before they decide to buy.

B2C Websites

On the other hand, with B2C websites, you usually don’t need to give your visitors as many options. A single option to “Add to Cart”, or perhaps an extra choice to “Add to Favorites” is all your user will need. Customers need to instantly see what they need to do next as soon as they arrive on a page:

On the Evil Hair website, you immediately see how to add a product to your cart.

Remember, the sales process is a lot quicker with B2C customers. This means that you need your CTA buttons to be front and center as soon as someone clicks on a page.

6. Contact Forms

In a similar vein, the way that you design your contact forms will also depend on the end-user that the website wants to appeal to. There’s a very different process for getting in touch on a B2B website, compared to a B2C site.

B2B Websites

B2B websites often require longer contact forms, as clients need to collect additional information about a prospect’s position in a company, and what that company does. B2B companies need to share things like what they’re looking for in a service, and how many users they have, so a sales team knows what kind of demonstration to give.

As with any strategy for contact form design, you should always only include the fields that your client needs and no more. If you demand too much from any client, you could send them running in the opposite direction. Check out this straightforward option from Ironpaper, for instance:

The form addresses as many relevant questions as possible without overwhelming the customer. Because the site handles things like design, it makes sense that they would ask for a link to the company’s existing website.

B2C Websites

On a B2C website, there are very different approaches to contact forms. You may have a dedicated contact form on your website where people can get in touch if they have any questions. A FAQ page where customers can serve themselves is another great way to help your client stand out from the competition. Check out this option from River Island, for instance:

On the other hand, you might implement pop-up contact forms into a website if your client wants to collect emails for email marketing. In that case, it’s important to make sure that you’re only asking for the information you need, and nothing more.

The easier it is to sign up for a newsletter, the more likely it is that customers will do it. Being able to enter their name and email address and nothing else will make the signup seem less tasking.

7. Search Bars and Navigation

Whether you’re designing for B2B or B2C companies, navigation will always be a critical concern. End users need to find it easy to track down the information that they need about a company, whether they’re looking for a particular product or a blog.

B2B Websites

On a B2B website, the search bar often takes up a lot less prominence than it does on a B2C site. That’s because all of the information that a client needs, and the buttons they need to take their next steps, are already visible front-and-center.

As a designer, it will be your job to push as many people to convert as possible, by making the purchasing journey the most appealing path for visitors. For instance, on the Copper website, the “Try Free” buttons are much easier to see than “Continue with Google” or “Login”:

With B2B sites, the focus is on a very specific goal. Although navigation still needs to be available, it doesn’t need to be as obvious as it is on a B2C site.

B2C Websites

On the other hand, most B2C websites offer a wide range of products, and they’re perfectly happy for their customers to purchase anything, as long as they eventually convert. Because of this, they make navigation a much more significant part of the customer journey.

The search bar is often presented at the very top of the screen where customers can see it immediately. Additionally, there may be multiple pages within certain product categories, so that customers can browse through the items they’re most interested in. For instance, look at the homepage on the IWoot website:

The navigation elements in B2C websites need to be a lot more obvious, because consumers are more likely to use them when they’re searching through their options.

8. Social Proof and Testimonials

Finally, social proof is one of the things that will work well for improving conversions on any kind of website. When your customers aren’t sure whether or not they should buy from you, a review or testimonial could be just the thing to push them over the edge.

B2B Websites

On a B2B website, the decision-making process takes a lot longer. Because of this, it’s worth including as much social proof as possible in every part of the website. Client testimonials, reviews and ratings, and even high-profile company logos make all the difference. Many B2B websites include a page dedicated to case studies highlighting the success of other brands.

Your client might even go as far as to ask for a page that highlights their awards and recognition or showcases comparison tables that pit their products against the competition.

For instance, Authority Hacker has a “what the pros say about us” section as social proof:

B2C Websites

With a consumer website, you can include consumer ratings and reviews wherever you like. However, it’s most likely that you’ll want to have a place where customers can see the reviews of other clients on the product pages themselves. On the EMP website the company gives users the option to click on the star review section to jump to a different space on the page where testimonials are listed. This ensures that customers don’t have to scroll through a lot of excess information if they just want to add an item straight to their cart.

Designing for B2B vs B2C

In the world of web design, no two customers are ever the same. While you’ll need to adapt your processes to suit each customer you interact with, you can set your expectations in advance by learning the differences between B2B and B2C strategies.

Featured images by Chris Ross Harris and Mike Kononov.

Source

Categories: Designing, Others Tags:

A Book Release For Click! And A Chance To Rethink Our Routines

July 10th, 2020 No comments
A sneak peek into the Click book

A Book Release For Click! And A Chance To Rethink Our Routines

A Book Release For Click! And A Chance To Rethink Our Routines

Ari Stiles

2020-07-10T10:30:00+00:00
2020-07-11T05:35:45+00:00

Paul Boag has written three books in the Smashing Library, and Click! How to Encourage Clicks Without Shady Tricks is just the most recent one. Paul wrote some articles for Smashing Magazine in addition to appearing on the Smashing Podcast and SmashingTV to promote the book and talk about some of its themes. Click! finally started shipping in June, and our beloved preorder customers found a surprise in those packages.

This Time, It’s Personal

Paul signed 500 postcards—designed by our own Ricardo Gimenez — and our first 500 buyers each received one of the signed postcards along with their copy of Click!

It was fun to watch the reactions pop up on social media:

Reading it in my car on this very moment!?? pic.twitter.com/TQHq8PyYFM

— Yakari Van Dessel (@yakarivd) June 15, 2020

What a lovley surprise today. I just revived a new book from @smashingmag. Many thanks to Paul Boag for a surprise note ? pic.twitter.com/VX7NH8WrJV

— Antonija ? (@AntonijaVresk) June 8, 2020

Who would have said that the book I purchased last month would arrive on my birthday! Best gift for myself ? thanks @smashingmag @paulboag pic.twitter.com/BZcirpJHyj

— Lu (@lubby_cat) June 9, 2020

this just got delivered before the weekend – good timing @smashingmag @boagworld pic.twitter.com/UmShqifaUe

— Jari Tirkkonen (@jatike) June 12, 2020

Look what came in the mail today!! This book is so relevant right now AND it looks so, so good on the inside. Wow. Thnx @boagworld and @smashingmag! Taking the rest of the day off now. Not really, but I wish I could. Man am I eager to fully read this. pic.twitter.com/d34UBpAxVI

— Marjolijn (@Marjolijn) June 10, 2020

The new @smashingmag landed in my mailbox this weekend ?? pic.twitter.com/rl3dAEd8a9

— Stanley van Heusden (@stannvanheusden) June 7, 2020

Haha, you’re welcome @smashingmag @boagworld pic.twitter.com/yBEKnurnvt

— Gijs Hosman (@gijshosman) June 10, 2020

Paul’s an experienced author, and we also had a very experienced illustrator for the cover and interior templates—Veerle Pieters! She has contributed artwork to Paul’s other books for Smashing, but she also designed the cover for our first Smashing Magazine Print edition. The illustrations and templates she provided for Click! helped make the book an inspiration to read, too.

A sneak peek into the Click book

Photo by Drew McLellan

Working with an experienced author and a seasoned illustrator is always inspiring. There were even a few pleasant surprises along the way:

@smashingmag keep this brillant idea ! pic.twitter.com/icFDRYwKNf

— Benoît HENRY (@bhenbe) June 14, 2020

Creativity In Quarantine

For a lot of us, quarantine has had a profound effect on our productivity levels. Feelings of being overwhelmed might be slowing you down, OR maybe your work is a welcome distraction, and you are getting a lot done right now.

One thing that has changed for most of us is our routines, though. This inevitably leads to some problem solving, which requires some creativity.

Click! comes along at a time when many of us need a creative “nudge.” The book inspires us to think differently about our routines for building online sites and services—what works, and what doesn’t.

“People are under enormous pressure to improve their conversion rates. Marketers have got targets they’ve got to meet, designers are under pressure … people are inevitably turning to dark patterns. Not because they want to, but because they’re under pressure to. They’re under pressure to bring about results.

So the premise of this book is, first of all, to explain why dark patterns are a bad idea. I talk about it from a purely business point of view, that these are the business reasons why dark patterns are ultimately damaging. And then that inevitably leads to the question of, well, if dark patterns aren’t the answer, then what is?

The majority of the book is exploring what you can do to improve your conversion rate without resorting to these kinds of more manipulative techniques.”

— Paul Boag, Smashing Podcast Episode 12


The Ethical Design Handbook

Print + eBook

$
39.00

Quality hardcover. Free worldwide shipping. 100 days money-back-guarantee.

eBook

$
19.00


Free!

DRM-free, of course.

ePUB, Kindle, PDF.
Included with Smashing Membership.


Get the eBook

Download PDF, ePUB, Kindle.
Thanks for being smashing! ??

Plenty Of Inspiration

We want to help you stay inspired! You might like

And, have you looked at Smashing Membership lately? Members have free access to our eBooks, job board, partner offers, SmashingTV webinars, and discounts on just about everything else Smashing has to offer.

More Smashing Books

Promoting best practices and providing you with practical tips to master your daily coding and design challenges has always been (and will be) at the core of everything we do at Smashing.

In the past few years, we were very lucky to have worked together with some talented, caring people from the web community to publish their wealth of experience as printed books that stand the test of time. Trine, Alla and Adam are some of these people. Have you checked out their books already?

Ethical Design Handbook

A practical guide on ethical design for digital products.

Add to cart $39

Design Systems

A practical guide to creating design languages for digital products.

Add to cart $39

Form Design Patterns

Form Design Patterns

A practical guide to designing and coding simple and inclusive forms.

Add to cart $39

Smashing Editorial
(ra, il)
Categories: Others Tags:

CSS Transitions In Vuejs And Nuxtjs

July 10th, 2020 No comments
Data on support for the css-transitions feature across the major browsers from caniuse.com

CSS Transitions In Vuejs And Nuxtjs

CSS Transitions In Vuejs And Nuxtjs

Timi Omoyeni

2020-07-10T09:00:00+00:00
2020-07-11T05:35:45+00:00

Transitions are a module of CSS that lets you create gradual transitions between the values of specific CSS properties. The behavior of these transitions can be controlled by specifying their timing function, duration, and other attributes. Using these transitions in your applications and websites create a better visual experience and sometimes draws and holds the user’s attention while a piece of information is being introduced to or leaving the screen. According to Can I Use, transitions are supported by most browsers, although there are some minor issues with Internet Explorer and Safari.

Data on support for the css-transitions feature across the major browsers from caniuse.com

Source: caniuse.com. (Large preview)

Vue.js is an open-source JavaScript framework for building client-facing web applications and single-page applications (SPA). One of the features of this framework is the ability to add transitions to an app seamlessly, to switch between either pages or components, and we’re going to look at how to do that in this tutorial.

Nuxt.js is also a JavaScript framework, built on top of Vue.js (and often referred to as a framework of a framework), for building server-side web applications, static-generated websites, as well as SPAs. It works the same as Vue.js, so if you know Vue.js, you shouldn’t have many issues getting started with Nuxt.js. Nuxt.js comes with two properties for adding transitions to an app, and we’re going to cover those as well in this tutorial.

This tutorial requires basic knowledge of either Vue.js or Nuxt.js. All of the code snippets in this tutorial can be found on GitHub.

What Is A Transition?

According to the Oxford Dictionary, a transition can be defined as:

“A passage in a piece of writing that smoothly connects two topics or sections to each other.

The process or a period of changing from one state or condition to another.”

In terms of physics, a transition is defined thus:

“A change of an atom, nucleus, electron, etc. from one quantum state to another, with emission or absorption of radiation.”

From these definitions, we get an idea on what a transition is. The definitions all involve two different things or states. In terms of code, a transition is not so different.

What Is A CSS Transition?

According to Mozilla’s web documentation:

“CSS Transitions is a module of CSS that lets you create gradual transitions between the values of specific CSS properties. The behavior of these transitions can be controlled by specifying their timing function, duration, and other attributes.”

This means we can define a CSS transition as: the change in the CSS property of one or more elements from one value to another.

The CSS transition property enables us to add a transition effect to any valid element. It consists of up to four other properties (five, if we count the transition property itself) that can be used individually or combined as a shorthand. Each property has a different function.

transition-property

The transition-property accepts the name of the CSS property that we want to watch out for changes on and whose change process we want to transition. It looks like this:

.btn {
  width: 200px;
  height: 50px;
  transition-property: width;
  background-color: red;
  color: #fff;
  border: 0;
}

But this property does not do anything without the next property.

transition-duration

The transition-duration property specifies the time that the change of the element(s) in the transition-property should go on for. This property is required in order for the transition to work. If it is not set (with a value greater than 0s), then the default value of 0s would mean it would not run. So, let’s set a duration for this transition:

.btn {
  width: 200px;
  transition-property: width;
  transition-duration: 2s;
  background-color: red;
  color: #fff;
  border: 0;
}

Here, we have an element with a class name of btn that has a width of 200px. We are using both the transition-property and the transition-duration properties here. What this means is, “Hey, CSS, watch out for when the width property changes, and when this happens, let the effect take 2s to change.”

So, if we have a button with a class name of btn, then the index.html file would look like this:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CSS Transitions</title>
    <link rel="stylesheet" href="./assets/styles.css">
</head>
<body>
    <Section>
        <h1>Hi CSS Transitions</h1>
        <button class="btn">Hover on me to see a cool transition</button>
    </Section>
</body>
</html>

Here, we have an HTML file that contains a button with a class that has transition-property and transition-duration properties watching out for changes to the element’s width.

One thing to note is that, in order for the transition on our button to work, we have to actually change the width of that element, either by manually adjusting the width with the developer tools in the browser, by using one of the CSS pseudo-classes, or by using JavaScript. For the purpose of this tutorial, we’re going to use the CSS pseudo-class :hover to change the width of the button:

// existing styles
.btn:hover {
  width: 300px;
}

Now, if we hover over this button, we should see the width of the button gradually increase over the set time, which is 2s.

See the Pen
transition-property and transition-duration
by Timi Omoyeni (@timibadass)
on CodePen.

transition-timing-function

The transition-timing-function property determines the speed at which the transition effect occurs. Five values are available for this property:

  • ease
    This (the default) specifies a transition effect that starts slowly, then gets fast, then ends slowly.
  • linear
    This specifies a transition effect with the same speed from start to end.
  • ease-in
    This specifies a transition effect with a slow start.
  • ease-out
    This specifies a transition effect with a slow end.
  • ease-in-out
    This specifies a transition effect with a slow start and end.
  • cubic-bezier(n,n,n,n)
    This lets you define your own values in a cubic-bezier function.

So, if we add ease-in to our button, we should notice the speed at which the width and height change, compared to the speed at which the button returns to its normal state. Here is our updated styles.css sheet:

.btn {
  width: 200px;
  height: 50px;
  transition-property: width;
  transition-duration: 2s;
  transition-timing-function: ease-in;
  background-color: red;
  color: #fff;
  border: 0;
}

If we want a more dramatic speed effect or the freedom to set a specific speed effect, we can use cubic-bezier(n,n,n,n):

btn {
    width: 200px;
    height: 50px;
    transition-property: width;
    transition-duration: 2s;
    transition-timing-function: cubic-bezier(0.075, 0.82, 0.165, 1);
    background-color: red;
    color: #fff;
    border: 0;
}

See the Pen
transition-timing-function
by Timi Omoyeni (@timibadass)
on CodePen.

One interesting thing about this value is that you can edit it directly in the browser using the developer tools.

cubic bezier in dev tools.

Cubic bezier in the browser’s developer tools. (Large preview)

If you click on the highlighted part of your developer tools, you’ll get an interface to modify the cubic-bezier options:

cubic bezier interface highlighted in yellow.

Cubic bezier interface highlighted in yellow. (Large preview)

As you move the two points around, the values of (n,n,n,n) change, and you’ll see a representation (highlighted in red) of how the speed effect will appear. This can be very useful when you have a specific speed effect in mind.

transition-delay

The transition-delay property sets how long (in seconds) the transition has to wait before its effect starts to occur. This time is different from the transition-duration property, which specifies how long the transition effect will take place.

.btn {
  width: 200px;
  height: 50px;
  transition-property: width;
  transition-duration: 2s;
  transition-timing-function: cubic-bezier(0.075, 0.82, 0.165, 1);
  transition-delay: 5s;
  background-color: red;
  color: #fff;
  border: 0;
}

If you try this in the browser, you will notice a delay before the element’s width starts to change. This is because of the transition-delay property and value that we have set.

See the Pen
transition-delay
by Timi Omoyeni (@timibadass)
on CodePen.

Shorthand Property

The individual transition properties can be tedious to use. For this reason, we have the shorthand property: transition. It accepts all of the properties in a defined order:

{
  transition: a b c d;
}

Here, the letters correspond as follows:

  • a: transition-property
  • b: transition-duration
  • c: transition-timing-function
  • d: transition-delay

We can refactor our existing transition to work using this shorthand property:

// from
.btn {
  width: 200px;
  height: 50px;
  transition-property: width;
  transition-duration: 2s;
  transition-timing-function: cubic-bezier(0.075, 0.82, 0.165, 1);
  transition-delay: 1s;
  background-color: red;
  color: #fff;
  border: 0;
}

// to
.btn {
  width: 200px;
  height: 50px;
  transition: width 2s cubic-bezier(0.075, 0.82, 0.165, 1) 1s;
  background-color: red;
  color: #fff;
  border: 0;
}

If we try this code in the browser, we will get the same transition effect that we got when we used the individual properties.

See the Pen
using shorthand property
by Timi Omoyeni (@timibadass)
on CodePen.

Transitions In Vue.js

Vue.js comes with two different ways to add transitions to an application. This doesn’t mean we cannot use transitions the CSS way. It just means that Vue.js’ developers have built on top of CSS to make it easier to use transitions. Let’s look at them one by one.

Transitioning Individual Elements and Components

One way we can use transitions in Vue.js is by wrapping the transition component around an element or component, using any of the following:

  • conditional rendering ( using v-if),
  • conditional display (using v-show),
  • dynamic components,
  • component root nodes.

When we are developing an application, there are instances when we want to display data to the user depending on a value (such as a boolean). Here’s an example of how this works, taken from the index.vue file:

<template>
  <div>
    <p v-if="show">Now you see me!</p>
    <p v-else>Now you don't!</p>
    <button @click="show = !show">click me</button>
  </div>
</template>
<script>
export default {
 data() {
   return {
     show: true
   }
 }
}
</script>
<style>
</style>

We have added two paragraphs to this page that appear depending on the value of show. We also have a button that changes the value of show when clicked. We’ll add this page to our App.vue file by importing it like so:

<template>
  <div id="app">
    <Index />
  </div>
</template>
<script>
import Index from "./components/index.vue";
export default {
  name: 'App',
  components: {
    Index
  }
}
</script>

If we open the browser, we should see our paragraph and button:

vue landing page when show is true.

Vue.js landing page in default state. (Large preview)

Right now, clicking the button changes only the value of show, which causes the visible text to change:

landing page when show is false.

Landing page when button is clicked. (Large preview)

Adding a transition to this paragraph can be done by wrapping both paragraphs in the transition component. This component accepts a name prop, which is very important for the transition to work.

<template>
  <div>
    <transition name="fade">
      <p v-if="show">Now you see me!</p>
      <p v-else>Now you don't!</p>
    </transition>
    <button @click="show = !show">click me</button>
  </div>
</template>

This name tells Vue.js which transition to apply to the elements or components inside this transition component. At this point, if we click on the button, we would still not notice any transition because we have yet to add the configuration for our transition in the form of CSS classes.

One thing to note is that, when using a transition between two elements of the same tag, we need to specify a key attribute on each element in order for the transition to occur.

<template>
  <div>
    <transition name="fade">
      <p v-if="show" key="visible">Now you see me!</p>
      <p v-else key="notVisible">Now you don't!</p>
    </transition>
    <button @click="show = !show">click me</button>
  </div>
</template>

Vue.js has six transition classes that are applied to the elements or components inside the transition component, and each of these classes represents a state in the transition process. We’re going to look at only a few of them.

v-enter

The v-enter class represents the “starting state for enter”. This is the point at which a condition (v-if or v-else) has been met and the element is about to be made visible. At this point, the class has been added to the element, and it is removed once the element has been added. The name prop (in this case, fade) attached to the transition component is prefixed to this class name, but without the v. This v can be used by default if name is not provided. Thus, we can add this class to our index.vue file:

<style>
p {
  color: green;
}

.fade-enter{
  color: red;
  transform: translateY(20px);
}
</style>

First, we add a color of green to all of the paragraphs on the page. Then, we add our first transition class, fade-name. Inside this class, we change the color to red, and we make use of the transform and translateY property to move the paragraph by 20px along the y-axis (vertically). If we try clicking on the button again, we will notice that very little or no transition takes place during the switch because we need to add this next class we’ll look at.

v-enter-active

The v-enter-active class represents the “whole entering” state of a transitioning element. It means that this class is added just before the element is inserted or becomes visible, and it is removed when the transition has ended. This class is important for v-enter to work because it can be used to add the CSS transition property to the class, together with its properties (transition-property, transition-duration, transition-timing-function, and transition-delay), some of which are needed in order for the transition effect to work. Let’s add this class to our app and see what happens:

.fade-enter-active {
  transition: transform .3s cubic-bezier(1.0, 0.5, 0.8, 1.0), color .5s cubic-bezier(1.0, 0.5, 0.8, 1.0);
}

See the Pen
vue transition enter state
by Timi Omoyeni (@timibadass)
on CodePen.

Now, if we click on the button, we will notice the transition of the color and the position of each of the texts as they come into view. But the transition from visible to hidden isn’t smooth enough because no transition is happening.

v-leave-active

The v-leave-active class represents the entire state in which an element changes from visible to hidden. This means that this class is applied from the moment an element starts to leave the page, and it is removed once the transition ends. This class is important in order for a leave transition to be applied because it takes in the CSS transition property, which also takes in other transition properties. Let’s add this to our app and see what happens:

.fade-leave-active {
  transition: transform 1s cubic-bezier(1.0, 0.5, 0.8, 1.0), color 1s cubic-bezier(1.0, 0.5, 0.8, 1.0);
}

See the Pen
vue transition leave active state
by Timi Omoyeni (@timibadass)
on CodePen.

When we click on the button now, we will notice that the element that should leave waits for approximately 2 seconds before disappearing. This is because Vue.js is expecting the next class with this transition to be added in order for it to take effect.

v-leave-to

The v-leave-to transition represents the “leaving” state, meaning the point at which an element starts to leave and its transition is triggered. It is added one frame after a leaving transition is triggered, and removed when the transition or animation finishes. Let’s add this class to our app and see what happens:

.fade-leave-to {
  transform: translateX(100px);
  color: cyan;
}

Clicking on the button, we will notice that each element that is leaving is sliding to the right as the color changes.

See the Pen
vue transition leave to state
by Timi Omoyeni (@timibadass)
on CodePen.

Now that we understand how transitions work in Vue.js, here’s an image that brings it all together:

classification of vue transition classes

Classification of Vue.js transition classes. (Large preview)

Finally, notice the not-so-smooth transition that occurs during the enter and leave states of elements that are transitioning. This is because Vue.js’ transitions occur simultaneously. Vue.js has a mode prop that helps us achieve a very smooth transition process. This prop accepts one of the following values:

  • in-out
    The new element transitions in first, and then, when it’s complete, the current element transitions out.
  • out-in
    The current element transitions out first, and then, when complete, the new element transitions in.

If we add this mode to our index.vue file and try again, we should see a better transition:

<template>
  <div>
    <transition name="fade" appear mode="out-in">
      <p v-if="show" key="visible">Now you see me!</p>
      <p v-else key="notVisible">Now you don't!</p>
    </transition>
    <button @click="transitionMe">click me</button>
  </div>
</template>

Now, if we click on the button, we will notice that one element leaves before another enters. This is a result of the mode we have selected for this transition. If we try the other mode, we will get a different behavior.

See the Pen
vue transition with mode
by Timi Omoyeni (@timibadass)
on CodePen.

List Transitions

If you ever try adding transitions to more than one element at a time using the transition component, an error will get printed to the console:

Vue transition error printed in console.

Vue.js error printed in console. (Large preview)

This is because the transition component is not meant to render more than one element at a time. If we want to transition two or more elements at a time or render a list (using v-for), we make use of the transition-group component. This component also accepts a name prop, but it has some differences from the transition component, including the following:

  • A key attribute is required for each element inside this component.
  • There is no need for the mode prop because more than one element would be rendered at a time.
  • A span element is rendered by default, but it can be modified by specifying a tag prop when defining the transition-group component. Let’s look at an example (in our listTransition.vue file):
    <template>
  <div>
    <h1>List/Group Transition</h1>
    <ul>
      <li v-for="user in users" :key="user.id">
        {{user.name}}
        <button>Remove</button>
      </li>
    </ul>
  </div>
</template>
<script>
export default {
  data() {
    return {
      users: [
        {
          name: "Vuejs",
          id: 1
        },
        {
          name: "Vuex",
          id: 2
        },
        {
          name: "Router",
          id: 3
        }
      ]
    };
  }
};
</script>
<style>
</style>

Here, we have an array of users, which we loop through using v-for, displaying the name in our template section. In order to be able to view this list, we need to import this component into the App.vue page:

<template>
  <div id="app">
    <Index />
    <listTransition />
  </div>
</template>
<script>
import Index from "./components/index.vue";
import listTransition from "./components/listTransition.vue";
export default {
  name: "App",
  components: {
    Index,
    listTransition
  }
};
</script>

Note that when using the transition-group component, instead of wrapping our list with a ul tag (or any tag we have in mind), we wrap it around the transition-group component and add the tag to the tag prop, like this:

<template>
  <div>
    <h1>List/Group Transition</h1>
    <transition-group name="slide-fade" tag='ul'>
      <li v-for="user in users" :key="user.id">
        {{user.name}}
        <button>Remove</button>
      </li>
    </transition-group>
  </div>
</template>
<script>
export default {
  data() {
    return {
      users: [
        {
          name: "Vuejs",
          id: 1
        },
        {
          name: "Vuex",
          id: 2
        },
        {
          name: "Router",
          id: 3
        }
      ]
    };
  }
};
</script>
<style>
.slide-fade-enter-active {
  transition: transform 0.3s cubic-bezier(1, 0.5, 0.8, 1),
    color 0.5s cubic-bezier(1, 0.5, 0.8, 1);
}
.slide-fade-leave-active {
  transition: transform 1s cubic-bezier(1, 0.5, 0.8, 1),
    color 1s cubic-bezier(1, 0.5, 0.8, 1);
}
.slide-fade-enter {
  color: mediumblue;
  transform: translateY(20px);
}
.slide-fade-leave-to {
  transform: translateX(100px);
  color: cyan;
}
</style>

Here, we have replaced the ul tag with the transition-group component, and added the ul as the tag prop value. If we inspect the updated page in the developer tools, we will see that the list is being wrapped in the element that we specified in the tag prop (that is, ul).

ul tag highlighted in dev tools.

The ul tag highlighted in the developer tools. (Large preview)

We have also added a transition name prop with a value of slide-fade to this component, with style rules below in the style section that follow this naming convention. For this to work, we need to add the following lines of code to our file:

<template>
  <div>
    <h1>List/Group Transition</h1>
    <transition-group name="slide-fade" tag="ul">
      <li v-for="user in users" :key="user.id">
        {{user.name}}
        <button @click="removeUser(user.id)">Remove</button>
      </li>
    </transition-group>
  </div>
</template>
<script>
export default {
  // ...
  methods: {
    removeUser(id) {
      let users = this.users.filter(user => user.id !== id);
      this.users = users;
    }
  }
};
</script>
  

In the template section, we add a click event to each button in the loop and pass the user.id to the removeUser method attached to this click event. We then create this function in the script section of our file. This function accepts an id as argument. Then, we run through our existing users and filter out the user with the id passed into this function. When this is done, we save our new array of users to the data of our page.

At this point, if you click on any of the buttons for the users, a transition effect will be applied as the user is being removed from the list.

See the Pen
Vue list transition
by Timi Omoyeni (@timibadass)
on CodePen.

Transitions In Nuxt.js:

Adding transitions to a Nuxt.js application is quite different from how you might be used to in Vue.js. In Nuxt.js, the transition component is automatically added to the application for you. All you need to do is one of the following.

Add It to Individual Page Component

Nuxt.js allows us to add transitions to an individual page component seamlessly. This transition is applied while the user is navigating to this page. All we have to do is add a transition property to the script section of the component. This property can be a string, a function, or an object. Some of the properties it accepts are:

  • name,
  • mode,
  • css.

Like Vue.js, Nuxt.js has a default name that gets assigned to a transition class if no name is provided, and it is called page. Let’s see how this works when we add it to our application in transition.vue:

<template>
  <div>
    <p>
      Lorem ipsum dolor sit amet consectetur adipisicing elit. Labore libero
      odio, asperiores debitis harum ipsa neque cum nulla incidunt explicabo ut
      eaque placeat qui, quis voluptas. Aut necessitatibus aliquam veritatis.
    </p>
    <nuxt-link to="/">home</nuxt-link>
  </div>
</template>
<script>
export default {
  transition: {
    name: "fade",
    mode: "out-in"
  },
  data() {
    return {
      show: true
    };
  }
};
</script>
<style>
p {
  color: green;
}
.fade-enter-active {
  transition: transform 0.3s cubic-bezier(1, 0.5, 0.8, 1),
    color 0.5s cubic-bezier(1, 0.5, 0.8, 1);
}
.fade-leave-active {
  transition: transform 1s cubic-bezier(1, 0.5, 0.8, 1),
    color 1s cubic-bezier(1, 0.5, 0.8, 1);
}
.fade-enter {
  color: mediumblue;
  transform: translateY(20px);
}
.fade-leave-to {
  transform: translateX(100px);
  color: cyan;
}
</style>

On this page, we’ve displayed “lorem ipsum” in the template section. We’ve also added the transition property, to which we have passed an object whose name is set to fade and whose mode is set to out-in. Finally, in the style section, we’ve added some styles that control the transition as the user navigates between this page and another.

In order for this transition to work, we have to navigate to /transition, but we would not notice any transition if we manually enter this route in our browser. So, let’s add a link to this page on the index.vue page.

<template>
  <div class="container">
    <div>
      // ..
      <nuxt-link to="/transition">next page</nuxt-link>
    </div>
  </div>
</template>

Now, if we click the link on either of the two pages, we will notice a sliding transition as the browser moves to and from the /transition route.

pageTransition

Adding transitions to individual pages can be challenging if we want to add them to all of the pages in the application. That’s where pageTransition comes in. This property allows us to add a general configuration for all of our pages in the nuxt.config.js file. This property accepts both a string and object as an option. Let’s see how that works in nuxt.config.js:

export default {
    // ...
    /*
     ** Global CSS
     */
    css: [
        '~/assets/transition.css'
    ],
    pageTransition: {
        name: "fade",
        mode: "out-in"
    },
}

Here, we’ve added the link to a CSS file, which we’ll create shortly. We have also added the pageTransition property to the file, along with with its configuration. Now, let’s create our CSS file, transition.css, and add the following styles to it:

.fade-enter-active {
    transition: transform 0.3s cubic-bezier(1, 0.5, 0.8, 1), color 0.5s cubic-bezier(1, 0.5, 0.8, 1);
}
.fade-leave-active {
    transition: transform 1s cubic-bezier(1, 1, 1, 1), color 1s cubic-bezier(1, 0.5, 0.8, 1);
}
.fade-enter {
    color: mediumblue;
    transform: translateY(20px);
}
.fade-leave-to {
    transform: translate3d(-500px, -300px 400px);
    color: cyan;
}

We’ve added the classes and styles that will be applied to the transition between one route and the other. If we get rid of the transition configuration from the transition.vue page and try to navigate between the two pages, we will get a transition effect.

layoutTransition

The layoutTransition property enables us to apply transitions based on the layout that the page is on. It works the same way as pageTranslation, except that it works based on layout. The default transition name is layout. Here’s an example of how it works, in nuxt.config.js:

export default {
    // ...
    /*
     ** Global CSS
     */
    css: [
        '~/assets/transition.css'
    ],
    layoutTransition: {
        name: "fade",
        mode: "out-in"
    },
}

Note that fade has to be the name of the layout in order for the transition to work with its layout. Let’s create this new layout in newLayout.vue to see what I mean:

<template>
  <!-- Your template -->
  <div>
    <h1>new layout</h1>
  </div>
</template>
<script>
export default {
  layout: "blog"
  // page component definitions
};
</script>

Conclusion

We have learned about CSS transitions and how to create them using the transition properties individually (transition-property, transition-duration, transition-timing-function, and transition-delay) and using the shorthand transition property. We have also covered how to apply these transitions in both Vue.js and Nuxt.js. But that’s not all. Vue.js has more ways for us to apply transitions in an application:

Related Resources

(ks, ra, yk, il)

Categories: Others Tags: