Wednesday, 24 February 2021

How Did US Stimulus Checks Impact On-Site Traffic and Conversions? [Case Study]

Posted by OeuyownK

As a Senior Analytics Strategist working at an agency with clients across industries, I’ve seen wildly contrasting performance throughout the pandemic. Certain online retailers and auto sites were far surpassing any historical performance, while others had to cut back budgets significantly. The variances in revenue performances also empirically correlated with time frames when the public received more support, in the form of stimulus checks.

My team at Portent conducted the study detailed below to verify our hypotheses that the pandemic caused revenue increases in online retailers and auto industries, and that those spikes correlated with stimulus distributions. We discovered a few specific factors that increased the probability of confirming our hypothesis along the way.

“Unprecedented” has undoubtedly been the word of the year, and it’s touched all aspects of life and business. There have been changes in consumer behavior across all industries — we’ve unfortunately seen swaths of shutdowns in particular markets while others have sustained or are even thriving. This post will provide some observations in online behavior along with some consumer data that should be used as predictive indicators through the rest of the pandemic.

The study

The observations of changes in online behavior were pulled and anonymized from 16 of our clients across 8 different industries. We narrowed those 8 industries down to three categories defined by Google Analytics for the purposes of this analysis: Shopping (10), Travel (3), and Autos & Vehicles (3).

The sites included in this analysis were limited to the US where possible and ranged in monthly revenue from $16K to $103K and in monthly sessions from 4K to 44K.

Observation #1: Stimulus checks resulted in increases in online behavior

Stimulus checks initiated the first revival of spending since the start of the pandemic. Granted, it was only about a month between the first notice of a lockdown and the beginning of stimulus payments. However, that increase in spend remained at higher levels after the majority of stimulus checks were distributed for most sites in this analysis—of course, excluding the Travel sites.

The first round of stimulus checks provided some form of relief to single Americans that made less than $99K a year, with those who made less than a $75K salary receiving the full $1,200. There were differences in limits depending on whether you have children or how you filed your taxes.

There was a noticeable jump in both sessions and revenue during the (1) week of April 13th, when $80M worth of stimulus payments were deposited for taxpayers who had direct deposits set up. By the (2) week of April 20th, additional rounds of deposits were made to those who manually set up direct deposits through the IRS. And by the (3) week of June 3rd, the IRS had delivered $270B in stimulus checks to Americans. At this point, revenue and sessions began to normalize below that period of stimulus distributions until the undeniable Black Friday sales occurred.

Observation #2: The impact depends on the market

There were obvious industries that were impacted most by the changes in consumer behavior and are still barely recovering: travel, in-store retail, and restaurants, to name those that were hit the hardest. On the other hand, some industries are actually performing better than before, such as online retail sales and food and beverage stores.

The analyses from S&P Global and the U.S. Census Bureau were accurately reflected in our study as well. Through the end of November, the average revenue for the Shopping sites in our analysis was 27.5% higher than our dip seen in March while sessions were 24.4% higher.

What came as a surprise, however, was that the Autos & Vehicles sites actually sustained higher averages than the Shopping sites. The sites in this industry saw 26.8% higher sessions and 36.8% higher revenue compared to the dip seen in the beginning of the pandemic and also well above prior levels in the beginning of the year.

The stark jump in sessions and revenue also aligned with when the distribution of stimulus checks began. In hindsight, the increase in consumer spending in this industry could have been anticipated considering the limitations and fear associated with traveling by plane. Online behavior is higher in the summer months as well, as those who were becoming restless from quarantining began to take road trips to satisfy their wanderlust.

There were a few other predictable trends that we identified in our study:

  1. There was one quick spike in athletic wear purchases with the average sustaining higher than pre-pandemic levels.
  2. There was a prolonged spike in revenue and especially traffic for baking goods and flour purchases, which remained at much higher levels compared to prior numbers. Then there was the seasonal influx of interest during the holidays. Interestingly, the conversion rate was 123% higher during the holidays compared to its peak in the beginning of the pandemic.
  3. With parents and families stuck at home, there was an exponential and lengthy growth in online behavior for children’s toys. Although the growth has tapered, it continues to see an upward trend.
  4. As expected, travel sites have taken the largest hit out of our study with a significant drop that has resulted in little to no recovery. The increase in revenue and sessions in the summer is almost entirely attributed to a resort that saw a similar increase in interest from the wanderlusts of the Autos & Vehicles sites.

Observation #3: There’s a positive correlation between AOV and % change in revenue

There was a fairly strong correlation of 0.76 between average order value (AOV) and % change in revenue YoY* for Shopping sites only. The consumer behavior on Autos & Vehicles sites was more dependent on stimulus checks and weather while the behavior on Travel sites was dependent on the feeling of safety.



*The data in this chart was pulled with the following notes:

  • YoY comparison was for November 2019 vs. November 2020 (November being the highest performing month based on seasonality)
  • Two anomalies were excluded from this data: (1) A flour company and, (2) A company with an AOV of nearly $2K

This one makes intuitive sense if you think about who’s been disproportionately impacted by the pandemic. Industries that are still thriving are ones that were able to more easily transition to 100% remote work and ones that had enough funds to weather some dropoff in clientele. Those who were fortunate enough to be employed in those industries during this time are also more likely to be paid higher than the median. In fact, only 30% of parents earning $200K or more lost their jobs since the pandemic, compared to 65% of parents earning less than $25K. Those who lost jobs in higher income brackets were also more likely to be able to find work again.

High-income spenders weren’t significantly impacted by the pandemic aside from the first few months, during which the change in consumer spending came from uncertainty. Although high- and low-income brackets both saw significant drops in spending initially, high-income consumers returned to levels comparable to January 2020 while low-income consumers were still about 10% below on average through September 2020.

Considerations to forecast future performance

There’s quite honestly nothing novel in this analysis that hasn’t been surfaced through market research, and these observations have been corroborated by economic data. The key takeaways here are to pay attention to the trends we're seeing, think about how they relate to your target audience or customer, and pay attention to new developments that may signal a shift toward normalcy once again as you re-enter the digital marketplace.

Stay informed of economic trends

Keep up-to-date with economic research published by S&P and monitor news releases from the Bureau of Economic Analysis to identify trends in Personal Income, Disposable Personal Income (DPI), Gross Domestic Product (GDP), and Personal Consumption Expenditures (PCE). The PCE started dipping in July, which correlates with the changes in consumer behavior we saw in our study. Although the reports don’t come out immediately, staying updated on the direction of these trends could inform your efforts.

Consider your target audience

It’s important to narrow down your research to your target audience. If your business is international, you likely won’t be as impacted by future stimulus checks in the US. However, different international markets will recover at differing rates.

Similarly, it’s important to keep your industry in mind. S&P is already estimating that the most-affected industries may not recover fully until 2022. This means that industries like in-store retail, travel, and service will have to find alternative ways to pivot during this time to return to normal levels.

Once you’ve considered your market and industry, weigh the risks based on your AOV and the income level of your average consumer. The higher the average income level, the more likely it is that your market has already recovered or the higher your chances are of being able to adjust successfully.

Additional federal support

Although the support from the US government throughout the pandemic has been lackluster at best, there’s a possibility of additional support. The recent round of stimulus checks were more limited than the first, meaning the impact on consumer behavior might be less noticeable. Economists are guessing that consumers would rather save this smaller amount than put it back into the economy. However, these bills should be accounted for in forecasting with the hopeful potential of additional (and more significant) federal support.

The distribution of vaccinations is likely to take at least several months to be impactful and possibly even longer to reach herd immunity. During this time of forward movement in the pandemic, we will all need to monitor and predict consumer behavior in unprecedented ways until we begin to see normalcy again.


Sign up for The Moz Top 10, a semimonthly mailer updating you on the top ten hottest pieces of SEO news, tips, and rad links uncovered by the Moz team. Think of it as your exclusive digest of stuff you don't have time to hunt down but want to read!



from The Moz Blog https://ift.tt/3dIy80S
via IFTTT

Tuesday, 23 February 2021

Hiding Content Responsibly

We’ve covered the idea of hiding things in CSS many times here, the most recent post being Marko Ilic’s “Comparing Various Ways to Hide Things in CSS” which did a nice job of comparing different techniques which you’d use in different situations. Hugo “Kitty” Giraudel has done something similar in “Hiding Content Responsibly” which looks at 10 methods—and even those, you could say, aren’t totally comprehensive.

Does this mean CSS is messy and incomprehensible? Nah. I feel like all the methods are logical, have good use cases, and result in good outcomes. Allow me to do a have a pretend conversation walking through my thought process here.

I need to hide this thing completely. For everyone.

No problem, that’s what the aria-hidden attribute is for.

I need to hide this thing, but only hide it for screen readers, not visually. (For example, an icon that has no additional meaning for screen readers, as there is an accessible label nearby.)

No problem, use display: none;.

I need to hide this thing, but only visually, not for screen readers. (For example, the contents of non-active tabs.)

No problem, use a .sr-only class. That leaves it accessible but hides it visually until you remove that class.

Oops, I actually want to hide this thing visually, but I still want it to take up physical space, not collapse. (For example, say a button has a loading spinner icon that is only needed when performing an action. The size of the button should factor in the size of that icon all the time, not just when the spinner is visible. That way, there’s no layout shifting when that icon comes and goes.)

No problem, use transform: scale(0) which will visually collapse it, but the original space will remain, and will leave it accessible to screen readers.

Oh nice, I could transition the transform, too, I suppose. But actually, that transition doesn’t fit my site well. I just want something I can fade out and fade in.

The opacity property is transitional, so transition that between 0 and 1 for fades. The good news is that visibility is also transitional. When fading out, use visibility: hidden, and when fading in, use visibility: visible to hide and unhide the thing from screen readers.


That’s not entirely comprehensive, but I find that covers 95% of hiding cases.


The post Hiding Content Responsibly appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.



from CSS-Tricks https://ift.tt/3dDAhL9
via IFTTT

What’s the Backup Plan for Your WordPress Site?

Of all the reasons we love and use Jetpack for CSS-Tricks—a poster child WordPress site—is that we can sleep easy at night knowing we have real-time backups running with Jetpack Backup. That way, no matter what, everything that makes this site tick, from all the template files to every single word we’ve ever typed, is always a click away from being restored if we need it for any reason at all.

There’s really no question whether or not you should be backing up your WordPress site. You absolutely should. It’s sort of like being prepared for an earthquake: you know it could happen at any time, so you want to make sure you’ve got all the tooling in place to keep things safe, not if, but when it happens.

What’s your backup plan? For us, it’s logging into WordPress.com, locating which backup to use, and clicking a button to restore things to that point in time. That’s all the files of course, like WordPress itself, the theme, and plugins, but also the entire database and all the media files.

Another reason we love Jetpack Backup? It provides a complete activity log of all the changes that happen on the site. It’s one thing to have your site backed up and be able to restore it. It’s another to know what caused the issue in the first place.

Jetpack Backup offers two plans one for daily backups and the other for real-time backups. We’ve got real-time running around here and that’s a great option for large sites that are updated often, like e-commerce. Most sites can probably get away with daily backups instead.

That leads to another wonderful thing: Jetpack Backup is sold à la carte. That means you can just get backups if that’s all you want from Jetpack. And, hey, if you find yourself needing more from Jetpack, like all the stuff we use it for here, then that rich feature set is just a couple of clicks away.

Not sure what your WordPress backup plan is? You really ought to check out Jetpack Backup. It works extremely well for us and we can’t recommend it enough.


True Story

While working on a bit of content for @css across team members, I noticed some of what I had written had disappeared. It got saved over by accident. I forgot to turn on “Revisions” for this Custom Post Type (it was a newsletter, which we write in WordPress).

It was tempting to be like, “Oh well, I’m a dummy, I’ll just have to remember and re-write it.” But no! I have Jetpack real-time backups on this site. I was able to find the exact moment I made my changes and download a copy of the site at that moment.

I didn’t need to restore the site to that point, just what I had written. So, I loaded up the wp_posts table from the SQL dump in that backup, plucked out my writing, and put it back in place.

And of course, I enabled revisions for that Custom Post Type so it won’t happen again.

Not only is that a true story, but this is a Jetpack double-whammy, because I “unrolled” that Twitter thread right here in WordPress via a Jetpack feature.


The post What’s the Backup Plan for Your WordPress Site? appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.



from CSS-Tricks https://ift.tt/2NQT8I2
via IFTTT

React Component Tests for Humans

React component tests should be interesting, straightforward, and easy for a human to build and maintain.

Yet, the current state of the testing library ecosystem is not sufficient to motivate developers to write consistent JavaScript tests for React components. Testing React components—and the DOM in general—often require some kind of higher-level wrapper around popular testing frameworks like Jest or Mocha.

Here’s the problem

Writing component tests with the tools available today is boring, and even when you get to writing them, it takes lots of hassle. Expressing test logic following a jQuery-like style (chaining) is confusing. It doesn’t jive with how React components are usually built.

The Enzyme code below is readable, but a bit too bulky because it uses too many words to express something that is ultimately simple markup.

expect(screen.find(".view").hasClass("technologies")).to.equal(true);
expect(screen.find("h3").text()).toEqual("Technologies:");
expect(screen.find("ul").children()).to.have.lengthOf(4);
expect(screen.contains([
  <li>JavaScript</li>,
  <li>ReactJs</li>,
  <li>NodeJs</li>,
  <li>Webpack</li>
])).to.equal(true);
expect(screen.find("button").text()).toEqual("Back");
expect(screen.find("button").hasClass("small")).to.equal(true);

The DOM representation is just this:

<div className="view technologies">
  <h3>Technologies:</h3>
  <ul>
    <li>JavaScript</li>
    <li>ReactJs</li>
    <li>NodeJs</li>
    <li>Webpack</li>
  </ul>
  <button className="small">Back</button>
</div>

What if you need to test heavier components? While the syntax is still bearable, it doesn’t help your brain grasp the structure and logic. Reading and writing several tests like this is bound to wear you out—it certainly wears me out. That’s because React components follow certain principles to generate HTML code at the end. Tests that express the same principles, on the other hand, are not straightforward. Simply using JavaScript chaining won’t help in the long run.

There are two main issues with testing in React:

  • How to even approach writing tests specifically for components
  • How to avoid all the unnecessary noise

Let’s further expand those before jumping into the real examples.

Approaching React component tests

A simple React component may look like this:

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

This is a function that accepts a props object and returns a DOM node using the JSX syntax.

Since a component can be represented by a function, it is all about testing functions. We need to account for arguments and how they influence the returned result. Applying that logic to React components, the focus in the tests should be on setting up props and testing for the DOM rendered in the UI. Since user actions like mouseover, click, typing, etc. may also lead to UI changes, you will need to find a way to programmatically trigger those too.

Hiding the unnecessary noise in tests

Tests require a certain level of readability achieved by both slimming the wording down and following a certain pattern to describe each scenario.

Component tests flow through three phases:

  1. Preparation (setup): The component props are prepared.
  2. Render (action): The component needs to render its DOM to the UI before either triggering any actions on it or testing for certain texts and attributes. That’s when actions can be programmatically triggered.
  3. Validation (verify): The expectations are set, verifying certain side effects over the component markup.

Here is an example:

it("should click a large button", () => {
  // 1️⃣ Preparation
  // Prepare component props
  props.size = "large";

  // 2️⃣ Render
  // Render the Button's DOM and click on it
  const component = mount(<Button {...props}>Send</Button>);
  simulate(component, { type: "click" });

  // 3️⃣ Validation
  // Verify a .clicked class is added 
  expect(component, "to have class", "clicked");
});

For simpler tests, the phases can merge:

it("should render with a custom text", () => {
  // Mixing up all three phases into a single expect() call
  expect(
    // 1️⃣ Preparation
    <Button>Send</Button>, 
    // 2️⃣ Render
    "when mounted",
    // 3️⃣ Validation
    "to have text", 
    "Send"
  );
});

Writing component tests today

Those two examples above look logical but are anything but trivial. Most of the testing tools do not provide such a level of abstraction, so we have to handle it ourselves. Perhaps the code below looks more familiar.

it("should display the technologies view", () => {
  const container = document.createElement("div");
  document.body.appendChild(container);
  
  act(() => {
    ReactDOM.render(<ProfileCard {...props} />, container);
  });
  
  const button = container.querySelector("button");
  
  act(() => {
    button.dispatchEvent(new window.MouseEvent("click", { bubbles: true }));
  });
  
  const details = container.querySelector(".details");
  
  expect(details.classList.contains("technologies")).toBe(true);
  expect(details.querySelector("h3").textContent, "to be", "Technologies");
  expect(details.querySelector("button").textContent, "to be", "View Bio");
});

Compare that with the same test, only with an added layer of abstraction:

it("should display the technologies view", () => {
  const component = mount(<ProfileCard {...props} />);

  simulate(component, {
    type: "click",
    target: "button",
  });

  expect(
    component,
    "queried for first",
    ".details",
    "to exhaustively satisfy",
    <div className="details technologies">
      <h3>Technologies</h3>
      <div>
        <button>View Bio</button>
      </div>
    </div>
  );
});

It does look much better. Less code, obvious flow, and more DOM instead of JavaScript. This is not a fiction test, but something you can achieve with UnexpectedJS today.

The following section is a deep dive into testing React components without getting too deep into UnexpectedJS. Its documentation more than does the job. Instead, we’ll focus on usage, examples, and possibilities.

Writing React Tests with UnexpectedJS

UnexpectedJS is an extensible assertion toolkit compatible with all test frameworks. It can be extended with plugins, and some of those plugins are used in the test project below. Probably the best thing about this library is the handy syntax it provides to describe component test cases in React.

The example: A Profile Card component

The subject of the tests is a Profile card component.

A card component where the persons name, photo, and number of posts are displayed to the left in a single column with a light red background, and the bio is displayed on the right in paragraph form with a title against a white background.

And here is the full component code of ProfileCard.js:

// ProfileCard.js
export default function ProfileCard({
  data: {
    name,
    posts,
    isOnline = false,
    bio = "",
    location = "",
    technologies = [],
    creationDate,
    onViewChange,
  },
}) {
  const [isBioVisible, setIsBioVisible] = useState(true);

  const handleBioVisibility = () => {
    setIsBioVisible(!isBioVisible);
    if (typeof onViewChange === "function") {
      onViewChange(!isBioVisible);
    }
  };

  return (
    <div className="ProfileCard">
      <div className="avatar">
        <h2>{name}</h2>
        <i className="photo" />
        <span>{posts} posts</span>
        <i className={`status ${isOnline ? "online" : "offline"}`} />
      </div>
      <div className={`details ${isBioVisible ? "bio" : "technologies"}`}>
        {isBioVisible ? (
          <>
            <h3>Bio</h3>
            <p>{bio !== "" ? bio : "No bio provided yet"}</p>
            <div>
              <button onClick={handleBioVisibility}>View Skills</button>
              <p className="joined">Joined: {creationDate}</p>
            </div>
          </>
        ) : (
          <>
            <h3>Technologies</h3>
            {technologies.length > 0 && (
              <ul>
                {technologies.map((item, index) => (
                  <li key={index}>{item}</li>
                ))}
              </ul>
            )}
            <div>
              <button onClick={handleBioVisibility}>View Bio</button>
              {!!location && <p className="location">Location: {location}</p>}
            </div>
          </>
        )}
      </div>
    </div>
  );
}

We will work with the component’s desktop version. You can read more about device-driven code split in React but note that testing mobile components is still pretty straightforward.

Setting up the example project

Not all tests are covered in this article, but we will certainly look at the most interesting ones. If you want to follow along, view this component in the browser, or check all its tests, go ahead and clone the GitHub repo.

## 1. Clone the project:
git clone git@github.com:moubi/profile-card.git

## 2. Navigate to the project folder:
cd profile-card

## 3. Install the dependencies:
yarn

## 4. Start and view the component in the browser:
yarn start

## 5. Run the tests:
yarn test

Here’s how the <ProfileCard /> component and UnexpectedJS tests are structured once the project has spun up:

/src
  └── /components
      ├── /ProfileCard
      |   ├── ProfileCard.js
      |   ├── ProfileCard.scss
      |   └── ProfileCard.test.js
      └── /test-utils
           └── unexpected-react.js

Component tests

Let’s take a look at some of the component tests. These are located in src/components/ProfileCard/ProfileCard.test.js. Note how each test is organized by the three phases we covered earlier.

  1. Setting up required component props for each test.
beforeEach(() => {
  props = {
    data: {
      name: "Justin Case",
      posts: 45,
      creationDate: "01.01.2021",
    },
  };
});

Before each test, a props object with the required <ProfileCard /> props is composed, where props.data contains the minimum info for the component to render.

  1. Render with a default set of props.

This test checks the whole DOM produced by the component when passing name, posts, and creationDate fields.

Here’s what the result produces in the UI:

And here’s the test case for it:

it("should render default", () => {
  // "to exhaustively satisfy" ensures all classes/attributes are also matching
  expect(
    <ProfileCard {...props} />,
    "when mounted",
    "to exhaustively satisfy",
    <div className="ProfileCard">
      <div className="avatar">
        <h2>Justin Case</h2>
        <i className="photo" />
        <span>45{" posts"}</span>
        <i className="status offline" />
      </div>
      <div className="details bio">
        <h3>Bio</h3>
        <p>No bio provided yet</p>
        <div>
          <button>View Skills</button>
          <p className="joined">{"Joined: "}01.01.2021</p>
        </div>
      </div>
    </div>
  );
});
  1. Render with status online.

Now we check if the profile renders with the “online” status icon.

And the test case for that:

it("should display online icon", () => {
  // Set the isOnline prop
  props.data.isOnline = true;

  // The minimum to test for is the presence of the .online class
  expect(
    <ProfileCard {...props} />,
    "when mounted",
    "queried for first",
    ".status",
    "to have class",
    "online"
  );
});
  1. Render with bio text.

<ProfileCard /> accepts any arbitrary string for its bio.

So, let’s write a test case for that:

it("should display online icon", () => {
  // Set the isOnline prop
  props.data.isOnline = true;

  // The minimum to test for is the presence of the .online class
  expect(
    <ProfileCard {...props} />,
    "when mounted",
    "queried for first",
    ".status",
    "to have class",
    "online"
  );
});
  1. Render “Technologies” view with an empty list.

Clicking on the “View Skills” link should switch to a list of technologies for this user. If no data is passed, then the list should be empty.

Here’s that test case:

it("should display the technologies view", () => {
  // Mount <ProfileCard /> and obtain a ref
  const component = mount(<ProfileCard {...props} />);

  // Simulate a click on the button element ("View Skills" link)
  simulate(component, {
    type: "click",
    target: "button",
  });

  // Check if the .details element contains the technologies view
  expect(
    component,
    "queried for first",
    ".details",
    "to exhaustively satisfy",
    <div className="details technologies">
      <h3>Technologies</h3>
      <div>
        <button>View Bio</button>
      </div>
    </div>
  );
});
  1. Render a list of technologies.

If a list of technologies is passed, it will display in the UI when clicking on the “View Skills” link.

Yep, another test case:

it("should display list of technologies", () => {
  // Set the list of technologies
  props.data.technologies = ["JavaScript", "React", "NodeJs"];
 
  // Mount ProfileCard and obtain a ref
  const component = mount(<ProfileCard {...props} />);

  // Simulate a click on the button element ("View Skills" link)
  simulate(component, {
    type: "click",
    target: "button",
  });

  // Check if the list of technologies is present and matches prop values
  expect(
    component,
    "queried for first",
    ".technologies ul",
    "to exhaustively satisfy",
    <ul>
      <li>JavaScript</li>
      <li>React</li>
      <li>NodeJs</li>
    </ul>
  );
});
  1. Render a user location.

That information should render in the DOM only if it was provided as a prop.

The test case:

it("should display location", () => {
  // Set the location 
  props.data.location = "Copenhagen, Denmark";

  // Mount <ProfileCard /> and obtain a ref
  const component = mount(<ProfileCard {...props} />);
  
  // Simulate a click on the button element ("View Skills" link)
  // Location render only as part of the Technologies view
  simulate(component, {
    type: "click",
    target: "button",
  });

  // Check if the location string matches the prop value
  expect(
    component,
    "queried for first",
    ".location",
    "to have text",
    "Location: Copenhagen, Denmark"
  );
});
  1. Calling a callback when switching views.

This test does not compare DOM nodes but does check if a function prop passed to <ProfileCard /> is executed with the correct argument when switching between the Bio and Technologies views.

it("should call onViewChange prop", () => {
  // Create a function stub (dummy)
  props.data.onViewChange = sinon.stub();
  
  // Mount ProfileCard and obtain a ref
  const component = mount(<ProfileCard {...props} />);

  // Simulate a click on the button element ("View Skills" link)
  simulate(component, {
    type: "click",
    target: "button",
  });

  // Check if the stub function prop is called with false value for isBioVisible
  // isBioVisible is part of the component's local state
  expect(
    props.data.onViewChange,
    "to have a call exhaustively satisfying",
    [false]
  );
});

Running all the tests

Now, all of the tests for <ProfileCard /> can be executed with a simple command:

yarn test

Notice that tests are grouped. There are two independent tests and two groups of tests for each of the <ProfileCard /> views—bio and technologies. Grouping makes test suites easier to follow and is a nice way to organize logically-related UI units.

Some final words

Again, this is meant to be a fairly simple example of how to approach React component tests. The essence is to look at components as simple functions that accept props and return a DOM. From that point on, choosing a testing library should be based on the usefulness of the tools it provides for handling component renders and DOM comparisons. UnexpectedJS happens to be very good at that in my experience.

What should be your next steps? Look at the GitHub project and give it a try if you haven’t already! Check all the tests in ProfileCard.test.js and perhaps try to write a few of your own. You can also look at src/test-utils/unexpected-react.js which is a simple helper function exporting features from the third-party testing libraries.

And lastly, here are a few additional resources I’d suggest checking out to dig even deeper into React component testing:


The post React Component Tests for Humans appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.



from CSS-Tricks https://ift.tt/3pOQuzw
via IFTTT

The Strategic Value of Structured Data Implementation on SME Websites

Posted by CrystalontheWeb

Structured data is one of the most effective ways to increase the visibility of your website content and increase the sustainability of your SEO as Google implements regular updates to the SERP environment. Over the last five years, many of Google’s most game-changing SERP features have been driven by the use of structured data from across the web. Google for Jobs, Google Shopping, featured snippets, how-to instructions, recipe cards, knowledge panels, and other rich snippets all serve content from sites with structured data.

So, when we think about how small and medium-sized enterprises (SMEs) can compete in today's ever-evolving SERP landscape, time and time again, well-implemented structured data is what makes the difference.

In this blog I’ll explain the following:

  • What is structured data?
  • Why should SMEs prioritize structured data implementation?
  • How do you identify which structured data is best for your SEO strategy?
  • Strategies for adding schema to your site
  • How to measure and demonstrate the impact of structured data

In my experience, well-implemented structured data is effective for websites of all sizes and in all verticals. For my own clients, schema implementation has enabled growth, improved performance on search and created opportunities to reach new audiences.

  • For an established national retail brand with a thriving social media following, schema optimisations contributed to a 50% increase in organic conversions within a month. And six months on, the improvements we made to product markup, organisation, and blog schema had helped drive a 230% increase in organic conversion value.
  • For a local recruitment site, we combined niche targeted schema and sitemap optimization to increase both organic clicks and impressions by over 80% each, within four months.
  • For an international B2B retailer, improving existing schema formed the basis for marketing strategy that enabled us to grow our tally of ranking keywords by an average of 70% across three countries, increase our revenue by 35% when compared to the previous period, and create new marketing channels, within 6 months.
  • For a professional services provider, we built E-A-T centric schema optimisations into a blog and were able to improve average ranking position by 30% in 3 months and by 43% within a year.

Though the target markets, objectives and audiences differed in each case, I was able to use schema markup as a strategic underpinning of a wider SEO and marketing strategy. This is because schema has become a fundamental element of scalable SEO.

What is structured data in SEO?

On a website, structured data is a means of defining content with a uniform set of names and values, so that bots and machines can better read, index, understand, and serve the content of your site. While the phrase “structured data” can include elements like open graph for social media, microdata, or indeed any set of data that is organized uniformly (think of your CRM), generally when SEOs talk about structured data, we’re referring to structured data markup in JSON-LD as specified by Schema.org and recommended by Google.

Why is Schema.org structured data so strategically important?

Schema.org has become structured data HQ, because its framework — sets of vocabularies and relationships — was created and is maintained through a cross-platform partnership between Google, Microsoft, Yandex, and other major search engines. They regularly create new schema types and relationships aimed at making the information on the web more easily accessible to users.

Schema.org breaks down content into common vocabulary of predefined @types, which each have predefined properties, and can then be expressed using a common Javascript notation (JSON-LD). Like entries to the Oxford English Dictionary, the team behind Schema.Org are constantly adding new @types and properties in order to keep pace with user needs. At present, there are 778 types, but that number will continue to grow. Each new type brings more clarity, consistency, and ease of access to the information on the web — something that’s brilliant for search engines, and great for your traffic.

What does that mean in practice?

Sometimes when I'm explaining structured data to clients, I describe it as a means of essentially turning your beautiful website into a spreadsheet for robots. They can prioritize and process the critical information about the content of the page without having to understand the layout of your particular Wordpress theme, reams of CSS, or navigate your Joomla configuration.

This means that information a bot has on a page can be more consistent and resilient, even if the content changes day-to-day. So, in the example of a retailer with seasonal specials and campaigns that change the front end home page layout, structured data tells Google the same information about the page in the same way every time:

Why should SMEs prioritize structured data implementation?

Simply put, structured data gives you the chance to jump the queue on the SERP.

When we look at the ways in which Google has enhanced its SERPs over the last few years, what we see consistently is the use of JSON-LD structured data in combination with Google APIs to create new features and new channels for content. Rich snippet SERP features like Google for Jobs, Google Shopping, featured snippets, how-to instructions, recipe cards, knowledge panels, and other monumental changes to the SERP have all been driven or improved by the creation and utilization of structured data frameworks.

Users love these features because they’re multi-media search enhancements, and are impossible to miss as they often take up the entire viewport on mobile:

Left to right: rich results for Google for Jobs, recipes, video


Not a plain blue link in sight.

In many cases, your content cannot be included in these attractive rich snippets without structured data. So, if you literally want to get ahead of the competition, structured data needs to be a component in your SEO strategy.

What are the other advantages of structured data for small businesses?

Along with increased visibility, structured data implementation offers the following advantages for small businesses:

  1. You will likely outpace your local competitors. SMEs are likely to feature within local pack search results with other small businesses. Here, competition for keywords is fierce, but many have yet to incorporate structured data into their sites. This is an opportunity to increase your visibility, gain more market share, and therefore increase conversions.
  2. Schema markup is a fully scalable optimization. While some SEO tasks like content creation can require pages to be optimized one-by-one, Schema markup can be built into the structure of the page. This means that once it’s set up, every new product listing page, for instance, would already have the optimization as you expand the site, whether you stock six products or six thousand. The time this saves is especially significant for small marketing teams.
  3. Schema markup implementation can be carried out as a single project within a few months. This can be a win for clients and SEOs, because in many cases, there is a clear demarcation before and after, followed by solid results which help to build confidence in further SEO activities, give clear ROI and satisfy clients looking for quick wins.

How do you identify which structured data is best for SEO strategy?

With almost 800 types of schema markup available to add to a website, it can be difficult to decide which are the best for your page, but to start, you can introduce or improve some new elements to help you better perform online and complement your existing content or e-commerce SEO strategy.

Does your site pass the schema markup need-to-have checklist?

There are certain sets of schema markup that apply to almost every site, and others — like Product and Job Postings — that are niche critical to effective SEO. As a general rule of thumb, every time I get a new client, I run through the following initial checks:

  • Do the homepage and about pages have Organisation or Local Business schema?
  • Do the blogs have schema for Articles or Blog Postings?
  • Do the team pages have Person schema?
  • If it’s an e-commerce site, does it have the niche critical Product schema?
  • If it is a recruiter site, does it have the niche critical Job Postings schema?
  • If the business is in another niche with dedicated Google SERP features, does it have the necessary markup?

If you answered “no” to any of these questions and the site doesn’t have the appropriate markup, then you should add schema markup to your site.

If the answer to these questions is “yes”, then it’s important to test the quality of the implementation before moving on to the next step. To do this, take a look at Search Console’s Rich Results Report to review pages at scale, or use their Structured Data Testing Tool and Rich Results Test to inspect individual pages. If you see errors, they should be addressed.

How to Find Address Schema Errors

Valid schema markup in Search Console

First, take a look at Search Console’s Rich Results Report to review pages at scale and identify which content is being read as Valid, Valid with Errors or Error.

Valid: If your markup is ‘Valid’, then it is being crawled and indexed correctly. These pages are unlikely to require further action.

Errors: Pages with markup that is identified with an ‘Error’ tend to have incorrect syntax, so you should review the individual page and correct the code as soon as possible. When the changes are complete, use the Validate Fix button, to request reassessment.

Valid with Warning: If your content is showing as ‘Valid a Warning’, then you are likely displaying schema markup with a Missing field. These warnings do not make the page or the markup invalid, but they can make the page less competitive, because the content is less targeted. Review your content to ensure that your schema is reflecting as much of the on page content as possible in order to reduce these errors, and therefore increase the performance of your schema markup.

Schema markup warnings in Search Console


Structured Data Testing Tool and Rich Results Test allow you to troubleshoot improvements to structured data on individual pages. Each of these tools you can enter the URL in question and you will receive itemised information on any errors or warnings.

Warnings on structured data testing tool
Warnings on rich results test


The missing fields highlighted here correspond to properties within the Event schema type. So, to improve this markup, you would look up the definitions of the relevant properties on schema.org and, where applicable, use their example HTML to guide your optimizations.

Property definitions in schema.org
Example "performer" HTML script from schema.org


In this instance, to improve the performance of my schema, I may need to build new performer fields into the CMS, or to work with the dev team to add the content from existing CMS data fields into the schema regex.

In either case you will be making improvements that help you better target and serve users.

Strategies for adding schema to your site

If you need to add schema to your site there are a few options for implementation.

Adding schema to single static pages

For some single pages with largely static content, adding markup types like Local Business, Organization, or a single FAQ page, can be a straightforward process of generating the code and placing it into the HTML of the page. Major CMS platforms like Shopify and Wordpress have plugins to assist with generating the markup for these pages which is easy to implement. Those with custom CMS configurations can use tools like the Schema Markup Generator to generate the JSON-LD, then pass it onto the development team to push it live.

Adding scalable schema for bulk implementation

Bulk schema implementation is almost essential for high volume content creators. This applies to e-commerce shops, but also to those who regularly post standard format content like recipes, blogs, articles, job vacancies, events, training courses, etc.

For these pages, the most effective way to get the most out of the schema on your site is to automate the process by building it into the structure of your site. In most instances, this involves a four phase approach, working in coordination with your developers and clients.

  • Start with your sitemap. You should have a dynamic XML sitemap that helps Google index pages as they are created, and includes the elements that are listed within the structured data. For an e-commerce site, this means having a sitemap that includes the product listings pages, but also the image sitemap and customer service pages.
  • Organize your content. For bulk implementation, you should work with your content, and try to assign a type and property to each standard field for content on your page. Treat it like a formula that can be applied to each page with the same format. If you don’t have fields that correspond with the required properties for your schema type, add them. If you have a bulk of information, try to ensure that you have properties that support the USPs of your content. Then work with your developers to update your template so that the schema generates consistently across the site.
  • Connect with relevant Google APIs. Once your sitemap is solid, your content is optimised and your markup is in place. check to see if the schema you're using has an API and, if it does, get your site connected to it. Some of the most-used rich results connect directly with dedicated Google APIs, which further integrate with PPC tools to round out your marketing mix.
Examples of Schema Types with Dedicated Google APIs
  • Lodging schema connects with the Hotel API and can be used with Google Hotels PPC
  • Job Posting schema connects with the Indexing API to enable inclusion in Google for Jobs
  • Product schema connects with Content API to enable inclusion in Google Shopping search results and ad listings.

How to measure and demonstrate the impact of schema markup

Measuring Schema Enable Rich Results in Search Console

The impact of schema markup which generates rich results, can be easily monitored and measured in Search Console. Within the Enhancements tab, you can monitor the quality of your implementation and any current or recent errors.

View schema-enabled rich content in the Search Console Enhancements tab


To monitor impressions, rankings, clicks and CTR, visit the Search Appearance tab under Performance. This tab provides historic data that can be compared to earlier configurations of the site.

Visit Performance > Search Appearance tab to see rich result performance


Within Google Analytics, your tracking and monitoring will depend upon your implementation. For instance, google-jobs-apply clicks may show as a separate source from standard search results within Organic. But I’ve also seen Google Shopping clicks show as part of the (other) channel. In either case, annotate your implementation dates to monitor relevant content for changes in clicks, impressions, and conversions.

For many small businesses, Search Console data should be sufficient but there are also tools which can help you drill down further into the data.

In summary

Taking a strategic, integrated approach to structured data implementation helps SMEs to stay competitive in today’s search environment because of its scalability, versatility and measurability. Furthermore, the applicability of schema markup as the underpinning of a cohesive content and advertising strategy, brings much needed efficiencies for SME marketers who want to make the most out of their content.


Want to learn more about technical SEO? Check out the Moz Academy Technical SEO Certification Series, an in-depth training series that hones in on the nuts and bolts of technical SEO.

Sign Me Up!

Sign up for The Moz Top 10, a semimonthly mailer updating you on the top ten hottest pieces of SEO news, tips, and rad links uncovered by the Moz team. Think of it as your exclusive digest of stuff you don't have time to hunt down but want to read!



from The Moz Blog https://ift.tt/3bBQXAm
via IFTTT

Monday, 22 February 2021

Getting Deep into Shadows

Let’s talk shadows in web design. Shadows add texture, perspective, and emphasize the dimensions of objects. In web design, using light and shadow can add physical realism and can be used to make rich, tactile interfaces.

Take the landing page below. It is for cycling tours in Iceland. Notice the embellished drop shadow of the cyclist and how it creates the perception that they are flying above not only the content on the page, but the page itself, as though they are “popping” over the screen. It feels dynamic and immediate, which is perfect for the theme of adventure.

A view of a BMX biker from above leaping over a vast area of light brown land with the words free ride along the bottom edge in large, bold, and white block lettering.
Credit: Kate Hahu

Compare that with this next example. It’s a “flat” design, sans shadows. In this case, the bike itself is the focal point. The absence of depth and realism allows the bike to stand out on its own.

Screenshot of a webpage with a light pink background with a white box that contains the site content with a headline that reads "Ride as Much or as Little" in red, an email subscription form, and a large image of a red and white bicycle to the right.
Credit: saravana

You can appreciate the differences between these approaches. Using shadows and depth is a design choice; they should support the theme and the message you want the content to convey.

Light and shadows

As we just saw, depth can enhance content. And what exactly makes a shadow? Light!

It’s impossible to talk about shadow without getting into light. It controls the direction of a shadow as well as how deep or shallow the shadow appears. You can’t have one without the other.

Google’s Material Design design system is a good example of employing light and shadows effectively. You’ve certainly encountered Material Design’s aesthetics because Google employs it on nearly all of its products.

A masonry grid of photos on a mobile screen. The purple header that contains the page title and hamburger menu has a shadow along its bottom edge that separates it from the white background of the photos.
White modal with a list of checkboxes. The modal has an underlying black shadow against the background.
A two-by-three grid of cards on a mobile screen. Each card has a light shallow shadow against a white background.

The design system takes cues from the physical world and expresses interfaces in three-dimensional space using light, surfaces, and cast shadows. Their guidelines on using light and shadows covers this in great detail.

In the Material Design environment, virtual lights illuminate the UI. Key lights create sharper, directional shadows, called key shadows. Ambient light appears from all angles to create diffused, soft shadows, called ambient shadows.

Shadows are a core component of Material Design. Compare that with Apple’s Human Interface Guidelines for macOS, where translucency and blurring is more of a driving factor for evoking depth.

Screenshot of Apple's Reminders app on a desktop. The left column that contains search and navigation is opaque and blends lightly into the desktop background while the solid white right column contains a checkbox list of reminders.
Screenshot of Apple's Maps app. The left column contains the map addresses and different route options with an opaque background that lightly blends in with the desktop background. The right column contains the map and does not blend in with the background.

In this case, light is still an influential factor, as it allows elements to either blend into the desktop, or even into other panels in the UI. Again, it’s is a design choice to employ this in your interface. Either way, you can see how light influences the visual perception of depth.

Light sources and color

Now that we understand the relationship between light and shadows, we ought to dig in a little deeper to see how light affects shadows. We’ve already seen how the strength of light produces shadows at different depths. But there’s a lot to say about the way light affects the direction and color of shadows.

There are two kinds of shadows that occur when a light shines on an object, a drop shadow and a form shadow.

Photo of an orange with light shining on it from the top right. That area is brighter than the left side which is covered in shadow. The ground contains a light reflection of the orange.

Drop shadows

A drop shadow is cast when an object blocks a light source. A drop shadow can vary in tone and value. Color terminology can be dense and confusing, so let’s talk about tone and value for a moment.

Tone is a hue blended with grey. Value describes the overall lightness or darkness of a color. Value is a big deal in painting as it is how the artist translates light and object relationships to color.

Illustration showing the effects of Hue, Tint, Tone, and Shade on red rectangles. Each rectangle is a slightly different shade of red where tint adds white, tone adds gray and shade adds black.

In the web design world, these facets of color are intrinsic to the color picker UI.

Form shadows

A form shadow, on the other hand, is the side of an object facing away from the light source. A form shadow has softer, less defined edges than a drop shadow. Form shadows illustrate the volume and depth of an object.

The appearance of a shadow depends on the direction of light, the intensity of light, and the distance between the object and the surface where the shadow is cast. The stronger the light, the darker and sharper the shadow is. The softer the light, the fainter and softer the shadow is. In some cases, we get two distinct shadows for directional light. The umbra is where light is obstructed and penumbra is where light is cast off.

Two vertically stacked illustrations.The top is a green circle with a yellow light source coming at it from the left and both umbra and penumbra shadows are cast to the right. The bottom illustration is the same green circle and light source, but with a solid black shadow cast to the right.

If a surface is close to an object, the shadow will be sharper. If a surface is further away, the shadow will be fainter. This is not some abstract scientific stuff. This is stuff we encounter every day, whether you realize it or not.

This stuff comes up in just about everything we do, even when writing with a pencil.

Light may also be reflected from sides of an object or another surface. Bright surfaces reflect light, dark surfaces absorb light.

These are the most valuable facets of light to understand for web design. The physics behind light is a complex topic, I have just lightly touched on some of it here. If you’d like to see explicit examples of what shadows are cast based on different light sources, this guide to drawing shadows for comics is instructive.

Positioning light sources

Remember, shadows go hand-in-hand with light, so defining a light source — even though there technically isn’t one — is the way to create impressive shadow effects. The trick is to consistently add shadows relative to the light source. A light source positioned above an element will cast a shadow below the element. Placing a light source to the left of an element will cast a shadow to the right. Placing multiple light sources to the top, bottom, left and right of an element actually casts no shadow at all!

Showing two browser mockups side by side. The left has light shining on it from all four directions showing uniform light and no shadows. The right has a single light source from the top casting a shadow along the bottom edge.

A light source can be projected in any direction you choose. Just make sure it’s used consistently in your design, so the shadow on one element matches other shadows on the page.

Elevation

Shadows can also convey elevation. Once again, Material Design is a good example because it demonstrates how shadows are used to create perceived separation between elements.

Showing a mobile screen flat on a light blue background with header, box, and navigational elements elevated over the screen showing depth.
Credit: Nate Wilson

Inner shadows

Speaking of elevation, the box-shadow property is the only property that can create inner shadows for a sunken effect. So, instead of elevating up, the element appears to be pressed in. That’s thanks to the inset keyword.

That good for something like an effect where clicking a button appears to physically press it.

It’s also possible to “fake” an inner text shadow with a little trickery that’s mostly supported across browsers:

Layering shadows

We’re not limited to a single shadow per element! For example, we can provide a comma-separated list of shadows on the box-shadow property. Why would we want to do that? Smoother shadows, for one.

Interesting effects is another.

Layering shadows can even enhance typography using the text-shadow property.

Just know that layering shadows is a little different for filter: drop-shadow() It’s syntax also takes a list, but it’s space-separated instead of comma-separated.

.box {
  box-shadow: 
    0 2px 2px #555, /* commas */
    0 6px 5px #777,
    0 12px 10px #999
  ;
}

.box {
  filter:
    drop-shadow(0 2px 2px #555) /* spaces */
    drop-shadow(0 6px 5px #777)
    drop-shadow(0 12px 10px #999);
}

Another thing? Shadows stack on top of one another, in the order they are declared where the top shadow is the first one in the list.

Two vertically stacked examples showing a white circle with a yellow and a grey circle behind it and the CSS code snippets that create the effect. On the top, the gray shadow is above the yellow shadow. On the bottom, the yellow shadow is above the gray shadow.

You may have guessed that drop-shadow() works a little differently here. Shadows are added exponentially, i.e. 2^number of shadows - 1.

Here’s how that works:

  • 1 shadow = (2^1 – 1). One shadow is rendered.
  • 2 shadows = (2^2 – 1). Three shadows are rendered.
  • 3 shadows = (2^3 – 1). Seven shadows are rendered.

Or, in code:

.one-shadow {
  filter: drop-shadow(20px 20px 0 grey);
}

.three-shadows {
  filter: 
    drop-shadow(20px 20px 0 grey)
    drop-shadow(40px 0 0 yellow);
}

.seven-shadows {
  filter: 
    drop-shadow(20px 20px 0 grey)
    drop-shadow(40px 0 0 yellow);
    drop-shadow(80px 0 0 red);
}

The <feDropShadow> element works the exact same way for SVGs.

Shadows and accessibility

Here’s something for you to chew on: shadows can help improve accessibility.

Google conducted a study with low-vision participants to better understand how shadows and outlines impact an individual’s ability to identify and interact with a component. They found that using shadows and outlines:

  • increases the ease and speed of finding a component when scanning pages, and
  • improves one’s ability to determine whether or not a component is interactive.

That wasn’t a wide-ranging scientific study or anything, so let’s turn around and see what the W3C says in it’s guidelines for WCAG 2.0 standards:

[…] the designer might darken the background behind the letter, or add a thin black outline (at least one pixel wide) around the letter in order to keep the contrast ratio between the letter and the background above 4.5:1.

That’s talking about light text on a light background. WCAG recommends a contrast ratio that’s at least 4.5:1 between text and images. You can use text shadows to add a stronger contrast between them.

Photo credit: Woody Van der Straeten

Shadows and performance

Before diving into shadows and adding them on all the things, it’s worth calling out that they do affect performance.

For example, filter: drop-shadow is hardware-accelerated by some browsers. A new compositor layer may be created for that element, and offloaded to the GPU. You don’t want to have too many layers, as it takes up limited GPU memory, and will eventually degrade performance. You can assess this in your browser’s DevTools.

Blurring is an expensive operation, so use it sparingly. When you blur something, it mixes the colors from pixels all around the output pixel to generate a blurred result. For example, if your <blur-radius> parameter is 2px, then the filter needs to look at two pixels in every direction around each output pixel to generate the mixed color. This happens for each output pixel, so that means a lot of calculations that grow exponentially. So, shadows with a large blur radius are generally slower to render than other shadows.

Did you know?

Did you know that shadows don’t influence the document layout?

A shadow is the same size as the element it targets. You can modify the size of a box-shadow (through the spread radius parameter), but other properties cannot modify the shadow size.

And did you know that a shadow implicitly has a lower z-index than elements? That’s why shadows sit below other elements.

And what about clipping and masking? If an element with a box-shadow is clipped (with clip-path) or uses a mask (with mask), the shadow isn’t shown. Conversely, if an element with text-shadow or filter: drop-shadow() is clipped, a shadow is shown, as long as it is within the clip region.

Here’s another: We can’t create oblique shadows (with diagonal lines) with shadow properties. That requires creating a shadow element and use a transform:skew() on it.

Oh, and one more: box-shadow follows border-radius. If an element has rounded corners, the shadow is rounded as well. In other words, the shadow mirrors the shape of the box. On the other hand, filter: drop-shadow() can create an irregular shape because it respects transparency and follows the shape of the content.

Showing two of the same card component side-by-side. They are brightly colored with a background gradient that goes from red to gold. The Nike logo is at the top, a title is below it, then a paragraph of white text beneath that. A red show with an exaggerated shadow is on both cards. The cards illustrated the difference between box shadow, which follows the boundaries of the card's edges, and drop shadow, which includes the shape of the shoe outside the card boundary.

Best use cases for different types of shadows

Practically anything on the web can have a shadow and there are multiple CSS properties and functions that create shadows. But choosing the right type of shadow is what makes a shadow effective.

Let’s evaluate the options:

  • box-shadow: This CSS property creates shadows that conform to the elements bounding box. It’s versatile and can be used on anything from cards to buttons to just about anything where the shadow simply needs to follow the element’s box.
  • text-shadow: This is a CSS property that creates shadows specifically for text elements.
  • filter: drop-shadow(): The CSS property here is filter, but what create the shadow is the drop-shadow function it accepts. What makes this type of shadow different from, say box-shadow, is that it follows the rendered shape of any element (including pseudos).
  • <feDropShadow>: This is actually an SVG element, whereas the rest are CSS properties. So, you would use this to create drop shadows directly in SVG markup.

Once you get the hang of the different types of shadows and each one’s unique shadow-creating powers, the possibilities for shadow effects feels endless. From simple drop shadows to floating elements, and even inner shadows, we can create interesting visuals that add extra meaning or value to UI.

The same goes for text shadows.

Shadows in the wild

Shadows are ubiquitous. We’re seeing them used in new and interesting ways all the time.

Have you heard the buzzword “neumorphism” floating around lately? That’s all about shadows. Here’s an implementation by Maria Muñoz:

Yuan Chuan, who makes amazing generative art, calls shadows a secret weapon in UI design:

CSS relies on existing DOM structure in the browser. It’s not possible to generate new elements other than ::before and ::after. Sometimes I really wish CSS had the ability to do so straightforwardly.

Yet, we can partially make up for this by creating various shadows and gradients entirely in CSS.

That’s why having drop-shadow is so exciting. Together with text-shadow and box-shadow we can do a lot more.

Just check out how he uses drop shadows to create intricate patterns.

Yes, that’s pretty crazy. And speaking of crazy, it’s worth mentioning that going too crazy can result in poor performance, so tread carefully.

What about pseudo-elements?

Oh yes, shadow properties are supported by the ::before and ::after pseudo-elements.

Other pseudos that respect shadows? The ::first-letter pseudo-element accepts box-shadow and text-shadow. The ::first-line pseudo-element accepts text-shadow.

Look at how Jhey Tompkins got all creative using box-shadow on pseudo elements to create animated loaders.

Animating shadows

Yes, we can make them move! The properties and function we’ve covered here are totally compatible with CSS animations and transitions. That means we can move shadows, blur shadows, expand/shrink shadows (with box-shadow), and alter the color.

Animating a shadow can provide a user with a cue that an element is interactive, or that an action has taken place. We saw earlier with our button example that an inset shadow showed that the button had been pressed. Another common animation pattern is elevating a card on hover.

If you want to optimize the animation performance, avoid animating box-shadow! It is more performant to animate drop-shadow(). But if you want the smoothest animation, a hack is the best option! Add an ::after pseudo-element with a bigger box-shadow, and animate its opacity instead.

Of course, there is a lot more you can animate. I will leave that exploration up to you!

Wrapping up

Phew, who knew there was so much to something as seemingly “simple” as CSS shadows! There’s the light source and how shadows are cast. The different types of shadows and their color. There’s using shadows for evoking depth, elevating elements and insetting them. There’s the fact that we can layer shadows on top of other shadows. And that we have a selection of CSS properties that we can use for different use cases. Then, there are the accessibility and performance implications that come with them. And, hey, animation is thing! That’s a heckuva lot!

Anyway, hopefully this broad overview gave you something new to chew on, or at the very least, helped you brush up on some concepts.


The post Getting Deep into Shadows appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.



from CSS-Tricks https://ift.tt/3bsmq7Y
via IFTTT

Passkeys: What the Heck and Why?

These things called  passkeys  sure are making the rounds these days. They were a main attraction at  W3C TPAC 2022 , gained support in  Saf...