How To Prepare for SOC 2 Compliance: SOC 2 Types and Requirements

To be reliable in today’s data-driven world, SOC 2 compliance is essential for all cloud-based businesses and technology services that collect and store their clients’ information. This gold standard of information security certifications helps to ensure your current data privacy levels and security infrastructure to prevent any kind of data breach. 

Data breaches are all too common nowadays among small to large scale companies across the globe in all sectors. According to PurpleSec, half of all data breaches will occur in the United States by 2023. 

Hi I’m bboycage

Hi, I'm bboycage and I work as a Data Analyst / Data Scientist at a Financial Consulting company. Python is my main language, had to learn SAS because of my job, along with the 1992 version of ANSI SQL as available through PROC SQL. I've also taken up Java on the side and plan on learning C++ down the line.

Automattic Acquires Frontity, Founders to Work Full-Time on Gutenberg

Frontity co-founders Pablo Postigo and Luis
Herranz

Automattic has acquired Frontity, the company behind an open source framework for building WordPress themes with React. The acquisition comes more than a year after the company raised €1M in funding in a round led by K Fund, with Automattic covering 22%. Frontity co-founders Pablo Postigo and Luis Herranz and their team will no longer be developing and maintaining the framework. Their new focus will be on contributing to the WordPress open source project and improving the full site editing developer experience.

“After a series of conversations, Automattic offered to sponsor our team to work directly on the WordPress open source project,” Frontity’s founders said in the announcement. “In particular, to contribute our expertise in developer experience, frontend tooling, performance, and UX to the WordPress core itself, instead of doing so only for an external tool.”

In a separate FAQ document, Frontity clarified that this acquisition does not mean the framework will be merged into WordPress, nor does it mean the team plans to bring React into the WordPress PHP or full site editing themes. The founders intend to apply their expertise to the Gutenberg project full time:

Even though Frontity is a React framework, it doesn’t mean that we are going to push React to the WordPress frontend. We will look at the Gutenberg and full site editing space to identify those areas in which our work could have the most significant impact, and work closely with the WordPress community to help improve its developer experience.

WordPress is already the best content platform on the web. We want to help it become the best development platform on the web.

In addition to putting the Frontity team on improving developer experience, Automattic is also investing in other ways that expand its support of the Gutenberg project. The company has recently hired a new head of developer relations who is building out a team tasked with improving the developer experience with Gutenberg and full-site editing. Birgit Pauli-Haack is a new member of that team and Automattic is also sponsoring her curation of the Gutenberg Times publication and the Changelog Podcast.

Frontity Framework Will Transition to a Community-Led Project

As the result of the acquisition and the team’s reassignment to working on Gutenberg, Frontity’s founders are transitioning the framework to be a community-led project. The team has prepared to leave the project in “a stable, bug-free position,” with documentation regarding what features they were working on. The framework is used by many companies and agencies, including high profile sites like the TikTok Creator Portal, popular Catholic news site Aleteia, and Diariomotor, a popular Spanish automotive publication.

“As far as we know, Automattic is not using Frontity Framework in any of its products,” Frontity CEO and co-founder Pablo Postigo said. “But we know there are a lot of Automatticians who have been following our progress closely. 

“We are aware that WordPress VIP does recommend Frontity for decoupled solutions, too. We are sure our experience and knowledge might be of help for this team as well.”

The departure of Frontity’s founders and team introduces some uncertainty into the future of the framework. When asked if it can survive as a community-led project, Postigo was optimistic but not certain.

“We still think that Frontity Framework is the best way to run a decoupled WordPress site with React and that this will be the case for a long time,” Postigo said.

“It is still too early to know what will happen. Frontity has a great community behind it, there are a lot of great projects which are using the framework in production, and there’s also a nice group of really active contributors. We feel really positive about the future of the framework.”

Google Chrome 94 Beta Includes WebCodecs API

Google has announced the beta release of v94 of Google Chrome and is highlighting the inclusion of a new WebCodecs API that is designed to handle low-level video processing at a broad level. This functionality was first introduced as an origin trial in Chrome 93. 

The Chromium blog outlined the importance of this new API in stating that:

Announce Your Plugin to the World, Shout It From the Rooftop

The easiest way to kill your WordPress plugin is to fail to let the world know about it. If you cannot manage a tweet, blog post, or quick note on Facebook, you may as well sign the death certificate then and there.

I get it. I have been there. Not everyone is a marketing guru, so putting out the right messaging might seem like speaking in a foreign language. But no messaging at all? That will not bode well for your young project.

Part of my job is finding plugins and sharing them with the community. Every week, I am on the lookout for that next great idea. Or, at least, a sort-of-good idea. I scour Twitter, regular blogs that I read, and official WordPress directories for plugins and themes. What I like most about writing about our beloved platform is not big business deals or the latest drama. While those pieces can be fun, I am most interested in what people create on top of the software. Whether a large company or an individual builds a new plugin, I am always excited when Monday rolls around. I can begin my search anew.

Often, I will find a new plugin that looks promising, so I dive into it. I install and activate it. At times, I find something so interesting that I have no choice but to share it. However, most of the time, I need a little push. To understand “the why” behind it. I do a quick check to see if they have written a blog post, tweeted about it, or shared it in some way. More often than not, nothing exists about it other than its listing in the plugin directory. And, reaching out to devs via email is often a hit-or-miss affair.

When you do not announce your new project to the world, it feels like you are not passionate about it.

I understand that some people simply hash out an idea and decide to drop it in the plugin directory. They are not in it for glory or even recognition. For them, it is just a piece of code they thought might come in hand for others. But, usage is the lifeblood of software. If no one else downloads, installs, and activates your plugin, can we really call it software?

Like the proverbial tree falling in the forest, whether it makes a sound is irrelevant if no one is around to hear it.

I have been mulling over whether to finishing writing this post for months, unsure if I was ever going to hit the publish button. I initially scratched down some notes in early April, attempting to understand why so few go through the trouble of doing any marketing of their plugins. I reached out to Bridget Willard to get insight from someone with a rich history in the marketing world. She had just published How to Market Your Plugin the month before, so the timing made sense.

However, I still felt too frustrated with the status quo in the WordPress community. A message from a reader wishing that we would mention alternative choices for plugin-related posts prompted me to revisit this. The truth is simple. So many projects fly under the radar because their authors begin and end their marketing by submitting to WordPress.org.

“Marketing is communication,” said Willard. “At the basic level, you must ‘tell people’ you have a product. The basic minimum is a blog post with social posts on Twitter, Facebook, and LinkedIn. It’s scary to market while you build, but that’s what the automobile industry does (along with others). You have to create the desire for the product — more than fixing a problem.”

While she tends to focus on products and services, I asked her what developers should be doing regardless of whether their plugins are commercial or free.

“I advocate with all of my being having a landing page on your main site (not a new site) promoting your plugin — while you’re building it,” paraphrasing from a chapter in her book. “Take signups for beta testers, start email marketing. The blog post is anti-climatic in many ways, and one or two tweets aren’t enough. Even better is to customize the sign-up ‘thank you page’ with something special — a video talking about your goals, for example. It’s not the time to have a tutorial or demo. This is about communicating your vision.

“The sad thing is that many plugin developers don’t see the need to spend money on a ‘free’ plugin. The axiom is true, ‘it takes money to make money.’ If you want sales, you need marketing. The sale for a free plugin is a download, and those are just as important.”

Part of me missed the old Weblog Tools Collection era. Every few days, the site would share a post with the latest plugins (themes too) with short descriptions of each. It was an easy win if you had no marketing skills. Developers could submit their new projects, and the team would share them with the community. When I was a young and upcoming developer, it was one of the only ways I knew how to reach folks in the WordPress community aside from pushing stuff from my own blog.

Today, we have far more avenues for sharing our work via social networking. Of course, the downside is that you have to cut through the noise.

In the long run, I would like to see an overhaul of the WordPress.org directory, focusing on the discoverability of plugins by feature instead of only popularity. Not all developers are known for their marketing skills. Having a little help from the directory they feed into could make it easier for budding developers to jump from hobby to business.

Until then, let the world know about your plugin. Even if it seems like you are shouting into the abyss, you may just hear an answer from someone who noticed your passion. If nothing else, let us know about it here at WP Tavern.

Greenhouse Review

Applicant tracking software (ATS) saves your HR team lots of time sorting candidates and moving them through the hiring and onboarding process.

Greenhouse is specifically designed to make applicant tracking more manageable and efficient with its suite of recruiting and onboarding tools.

Plus, its onboarding features provide a one-of-a-kind experience for new hires that other ATS options don’t offer. 

I’ve dug deep into Greenhouse to see what sets it apart from competitors and how it stands up against some of our top picks. 

Read on for an in-depth review. 

Greenhouse Pros and Cons 

Pros 

  • Interview scorecards reduce bias
  • Customizable recruiting workflow
  • Simple, straightforward job setup
  • Customizable offer templates save time
  • Lots of integrations
  • Extensive knowledge base

Cons 

  • Can be buggy with specific tasks
  • Separate pricing for recruiting and onboarding
  • Lacking in collaboration features
  • User interface options can be overwhelming 
  • No customized training for new users
Compare The Best Applicant Tracking Providers
We reviewed dozens of applicant tracking providers and narrowed them down to the best options.
See Top Picks

How Greenhouse Compares to Top Applicant Tracking Software

Greenhouse has both recruiting and onboarding solutions for businesses to move through the hiring process smoothly. Its job-posting and candidate-sourcing tools help automate your pipeline, and reports ensure hiring and onboarding efficiency.

Compared to others, this software is highly customizable for your hiring team, has plenty of integrations with your favorite tools, and is easy to get the hang of within a few minutes. One of its best features—interview scorecards—allows interviewers to gain objective feedback on a candidate’s interview.

Still, Greenhouse doesn’t appear on the list of our top picks of the best applicant tracking software. BambooHR and JazzHR are our picks for most businesses because of their varied features and ease of use. Greenhouse displays these characteristics, too. But a few flaws, like an option-heavy interface and a need for more collaborative features, prevent it from being worthy of our list of favorites. 

While it may not have made the list for its ATS, Greenhouse did make the cut when we researched and reviewed the top recruiting software on the market–something to keep in mind.

Greenhouse Hiring Volume and Frequency Capabilities

Greenhouse isn’t necessarily the best ATS option for businesses that only hire a handful of employees each month or year. The software can get pricey for small businesses, especially if they want both the recruiting and onboarding tools, as they’re technically separate products with different prices. 

Medium and large businesses with significant hiring needs will undoubtedly benefit from Greenhouse. For example, Stack reports that 37% of Greenhouse’s customers are mid-sized with 51-250 employees. 

Greenhouse doesn’t limit the number of people you hire or limit much of anything, really. The company creates a custom solution for each client, including recruiting features and a pricing structure that works with their needs. If there are particular features you need, like unlimited job postings, but you want to save money by limiting the number of people you can hire each month, Greenhouse can work with you on a custom plan.

Additionally, Greenhouse is scalable. You can start as a small or medium business and change your plan to suit your growth as you become a larger company. You can also promote scalability within the software by adding more roles, customizing your workflow, and automating applications and approvals.

Greenhouse Software Type

Greenhouse is designed for in-house hiring, meaning it’s made with your hiring team or HR department in mind rather than the needs of a staffing agency. In this respect, it has all the tools your team needs to review applications, qualify candidates, set up interviews, and move candidates through your onboarding process.

One of the ways in which Greenhouse caters to in-house teams is through its structured hiring process, which creates a defined set of attributes and requirements for an ideal candidate. Your team can set this up how they’d like, but the ultimate goal is to ensure a unified hiring process with all hiring agents on the same page. Automation, interview scorecards, and reporting optimize the process and save your team time.

Although Greenhouse is mostly for in-house hiring, you can still use the help of an agency if you’d like. Greenhouse allows agency access through an Agency Portal, for which admins can control permissions. Send an invite to the agency, and recruiters can set up an agency account to navigate the portal. The portal allows recruiters to send your company job prospects to your Greenhouse dashboard without disrupting your workflow or accessing settings.

If you’re looking for more control as a staffing agency, try JazzHR, which offers unlimited users and jobs with modest pricing compared to Greenhouse.

Greenhouse Human Resources Features

In addition to Greenhouse recruiting solutions, the company also offers its onboarding solutions, making it an excellent fit for your HR department. Important note: You’ll need to pay for each product separately, which can drive up prices. 

But the software’s onboarding tools are a must for HR departments looking for ways to transition new team members into their roles quickly and efficiently. Not only does Greenhouse smooth the process for the HR team, but it also enhances the process for your new employees.

On the backend, your HR team can assign roles for onboarding tasks, set reminders, sync Greenhouse Recruiting information, and craft emails that detail onboarding steps for new employees. You can also set up an automation for each completed step to notify team members when new recruits are ready to move on or open up skills assessments or training videos for new team members.

If you’d like even more of a complete HR solution, BambooHR might be the best option. BambooHR includes applicant tracking and onboarding but adds the perks of compensation and offboarding features, giving it everything your team needs to take care of your employees.

Greenhouse Pricing

I mentioned previously that Greenhouse charges separately for onboarding and recruiting tools, so you’ll pay more for both than for one. Still, the products relatively line up with similar product pricing and may even be more affordable. A 2017 Siftery report shows that similar products, like Jobvite and iCIMS, have higher average annual pricing than Greenhouse for more than 500 employees.

Unfortunately, smaller teams tend to experience higher pricing with Greenhouse than with similar products. The same report notes Greenhouse users as paying more annually, on average, than those with competing companies if they have 500 or fewer employees. 

Greenhouse features three plans—Essential, Advanced, and Expert—but you’ll need to talk to an Account Executive to determine which one might be better for your needs. Greenhouse can also create custom solutions for your team with a mix of features that work best for your firm.

Pricing isn’t available on the Greenhouse website and instead fluctuates depending on your company size and necessary features. However, the Siftery report shows that most companies should expect to pay at least $5,000 a year to access the Greenhouse software, which could be more than a small business’s budget allows.

Greenhouse Recruiting and Talent Sourcing

One of two primary product offerings from Greenhouse, Recruiting includes all the tools your team needs to optimize its hiring process and find the best talent for the job. With Recruiting, your team can develop a step-by-step pipeline that posts jobs, tracks applications, screens candidates, and finishes the process, thereby automating some tasks to save time.

Greenhouse Recruiting gives you access to more than 1,000 top job boards to sync your job listings where top talent is likely to find them. You’ll even get industry-based insights into what job boards are best suited for your jobs. 

Then, Greenhouse really comes alive. Created automated surveys to help you screen candidates, receive notifications during each workflow step to stay on top of the process, and communicate with your hiring team from within your dashboard. Your employees can also create a referral system to help you find the best candidates.

In-house teams will get the most benefits from Greenhouse Recruiting, although you can invite a recruiting agency to work within its own section of your account. To better handle recruiting needs if you’re an agency, you might opt for an agency-focused software like Bullhorn, which has the capabilities to handle mass numbers of applicants.

Greenhouse Onboarding

The other primary Greenhouse product is Onboarding, which handles everything that comes after recruiting. With Onboarding, your team will know exactly where each candidate is in the onboarding process, and new hires will have a seamless, engaging experience as they navigate each step.

Your team can send policies and other pertinent company information to new hires, introduce them to their teams, and create emails to notify them of their next onboarding steps. Along the way, Greenhouse can set alerts and reminders to your team as new hires complete steps or fill out necessary documents. Greenhouse also gives your new hires a chance to provide feedback about the onboarding process so that you can continue to improve it. 

If your budget is a primary concern, Greenhouse Onboarding might exceed it, especially if you’re a smaller company. Alternatively, try an onboarding software like WebHR, which includes recruiting and onboarding modules for just $2 per employee per month—excellent pricing if you have 25 or fewer team members involved.

Greenhouse Diversity, Equity, and Inclusion Features

A primary focus of Greenhouse Recruiting software is making the hiring process an inclusive and fair one, leading you to a diverse mix of candidates free from bias. Candidates can also feel welcome and equal, thanks to features that put them in control of their preferences. Greenhouse is one of the best ATS software options for teams prioritizing diversity.

For instance, candidates can define their pronouns, record their name pronunciation, and view your company’s mission statement and culture on your career page. You can also set up custom demographic questions in an application for candidates to fill out optionally.

An interview scorecard then assists the hiring team with making fair assessments based on a candidate’s actual skills to remove any personal bias. The scorecard lists key attributes necessary for a position, and an interviewer can score the applicant based on their abilities. If desired, you can include a required note section for team members to provide detailed feedback to explain their scoring.

Additionally, Greenhouse provides reports based on demographic information from candidates that you can use to tweak your hiring strategy and ensure inclusion across all departments. 

Greenhouse Mobile App

While many applicant tracking software options are on the market, many of them do not have a mobile app to take your hiring on the go. But Greenhouse does, allowing you to continue recruiting from anywhere.

With the Greenhouse Recruiting app, you can handle all basic recruiting tasks from your smartphone or tablet. Check out and approve applications, view candidate profiles and attachments, and browse your company’s open job positions and potential candidates. The app also displays pipeline information, like where applications are in the approval process and how many upcoming interviews your team has.

There’s also a Greenhouse Events app, which is a must for hiring teams hosting in-person events. Use the app to collect candidate data quickly for follow-up, and organize prospects for convenient searchability when you’re ready to move forward. 

Greenhouse Reporting

Seeing how your hiring team and process perform day in and day out is necessary to ensure efficiency, just like any other company department. The better the team gets at finding suitable candidates, the less time they’ll spend posting jobs, sourcing prospects, and onboarding new team members. That’s where Greenhouse Reporting comes into play.

Greenhouse can generate dozens of reports to help you learn more about candidates, your pipeline’s efficiency, and your job opening statuses. You can create reports from templates or build custom reports from scratch to give you the precise details you need.

Greenhouse’s reports are easy to decipher but may not provide the more granular analytics you need if you’re looking for more in-depth information. Custom reporting can help, but it still fails to get into the details some HR teams might prefer. For this, try JazzHR’s Advanced Reporting module, with detailed reports on candidates, jobs, compliance, and more. You can add the module to a Plus Plan.

Compare The Best Applicant Tracking Providers
We reviewed dozens of applicant tracking providers and narrowed them down to the best options.
See Top Picks

Greenhouse excels in saving your team time setting up job postings, moving candidates down your hiring pipeline, and reducing bias during the process. Still, it has a few points that prevent it from being one of our top choices, including its prices for SMBs and lack of collaboration features for teams. I recommend requesting a Greenhouse demo to see it in action and ensure that it has features and reporting capabilities that work for your team.

Exploring the CSS Paint API: Blob Animation

After the fragmentation effect, I am going to tackle another interesting animation: the blob! We all agree that such effect is hard to achieve with CSS, so we generally reach for SVG to make those gooey shapes. But now that the powerful Paint API is available, using CSS is not only possible, but maybe even a preferable approach once browser support comes around.

Here’s what we’re making. It’s just Chrome and Edge support for now, so check this out on one of those browsers as we go along.

Live demo (Chrome and Edge only)

Building the blob

Let’s understand the logic behind drawing a blob using a classic <canvas> element to better illustrate the shape:

When talking about a blob, we’re also talking about the general shape of a distorted circle, so that’s the shape we can use as our base. We define N points that we place around a circle (illustrated in green).

const CenterX = 200;
const CenterY = 200;
const Radius = 150;
const N = 10;
var point = [];

for (var i = 0; i < N; i++) {
  var x = Math.cos((i / N) * (2 * Math.PI)) * Radius + CenterX;
  var y = Math.sin((i / N) * (2 * Math.PI)) * Radius + CenterY;
  point[i] = [x, y];
}

Considering the center point (defined by CenterX/CenterY) and the radius, we calculate the coordinate of each point using some basic trigonometry.

After that, we draw a cubic Bézier curve between our points using quadraticCurveTo(). To do this, we introduce more points (illustrated in red) because a cubic Bézier curve requires a start point, a control point, and an end point.

The red points are the start and end points, and the green points can be the control points. Each red point is placed at the midpoint between two green points.

ctx.beginPath(); /* start the path */
var xc1 = (point[0][0] + point[N - 1][0]) / 2;
var yc1 = (point[0][1] + point[N - 1][1]) / 2;
ctx.moveTo(xc1, yc1);
for (var i = 0; i < N - 1; i++) {
  var xc = (point[i][0] + point[i + 1][0]) / 2;
  var yc = (point[i][1] + point[i + 1][1]) / 2;
  ctx.quadraticCurveTo(point[i][0], point[i][1], xc, yc);
}
ctx.quadraticCurveTo(point[N - 1][0], point[N - 1][1], xc1, yc1);
ctx.closePath(); /* end the path */

Now all we have to do is to update the position of our control points to create the blob shape. Let’s try with one point by adding the following:

point[3][0]= Math.cos((3 / N) * (2 * Math.PI)) * (Radius - 50) + CenterX;
point[3][1]= Math.sin((3 / N) * (2 * Math.PI)) * (Radius - 50) + CenterY;

The third point is closest to the center of our circle (by about 50px) and our cubic Bézier curve follows the movement perfectly to keep a curved shape.

Let’s do the same with all the points. We can use the same general idea, changing these existing lines:

var x = Math.cos((i / N) * (2 * Math.PI)) * Radius + CenterX;
var y = Math.sin((i / N) * (2 * Math.PI)) * Radius + CenterY;

…into:

var r = 50*Math.random();
var x = Math.cos((i / N) * (2 * Math.PI)) * (Radius - r) + CenterX;
var y = Math.sin((i / N) * (2 * Math.PI)) * (Radius - r) + CenterY;

Each point is offset by a random value between 0 and 50 pixels, bringing each point closer to the center by a slightly different amount. And we get our blob shape as a result!

Now we apply that shape as a mask on an image using the CSS Paint API. Since we are dealing with a blobby shape, it’s suitable to consider square elements (height equal to width) instead, where the radius is equal to half the width or height.

Here we go using a CSS variable (N) to control the number of points.

I highly recommend reading the first part of my previous article to understand the structure of the Paint API.

Each time the code runs, we get a new shape, thanks to the random configuration.

Let’s animate this!

Drawing a blog is good and all, but animating it is better! Animating the blob is actually the main purpose of this article, after all. We will see how to create different kinds of gooey blob animations using the same foundation of code.

The main idea is to smoothly adjust the position of the points — whether it’s all or some of them — to transition between two shapes. Let’s start with the basic one: a transition from a circle into a blob by changing the position of one point.

Animated gif shoeing a cursor hovering the right edge of a circular image. The right side of the image caves in toward the center of the shape on hover, and returns when the cursor leaves the shape.
Live demo (Chrome and Edge only)

For this, I introduced a new CSS variable, B , to which I am applying a CSS transition.

@property --b{
  syntax: '<number>';
  inherits: false;
  initial-value: 0;
}
img {
  --b:0;
  transition:--b .5s;
}
img:hover {
  --b:100
}

I get the value of this variable inside the paint() function and use it to define the position of our point.

If you check the code in the embedded linked demo, you will notice this:

if(i==0) 
  var r = RADIUS - B;
else
  var r = RADIUS

All the points have a fixed position (defined by the shape’s radius) but the first point specifically has a variable position, (RADIUS - B ). On hover, The value of B is changing from 0 to 100, moving our point closer to the middle while creating that cool effect.

Let’s do this for more points. Not all of them but only the even ones. I will define the position as follow:

var r = RADIUS - B*(i%2);
An animated gif showing a cursor hovering over a circular image. The shape of the image morphs to a sort of star-like shape when the cursor enters the image, then returns when the cursor leaves.
Live demo (Chrome and Edge only)

We have our first blob animation! We defined 20 points and are making half of them closer to the center on hover.

We can easily have different blobby variations simply by adjusting the CSS variables. We define the number of points and the final value of the B variable.

Live demo (Chrome and Edge only)

Now let’s try it with some random stuff. Instead of moving our points with a fixed value, let’s make that value random move them all around. We previously used this:

var r = RADIUS - B*(i%2);

Let’s change that to this:

var r = RADIUS - B*random();

…where random() gives us a value in the range [0 1]. In other words, each point is moved by a random value between 0 and B . Here’s what we get:

Live demo (Chrome and Edge only)

See that? We get another cool animation with the same code structure. We only changed one instruction. We can make that instruction a variable so we can decide if we want to use the uniform or the random configuration without changing our JavaScript. We introduce another variable, T, that behaves like a boolean:

if(T == 0) 
  var r = RADIUS - B*(i%2);
else 
  var r = RADIUS - B*random();

We have two animations and, thanks to the T variable, we get to decide which one to use. We can control the number of points using N and the distance using the variable V. Yes, a lot of variables but don’t worry, we will sum up everything at the end.

What is that random() function doing?

It’s the same function I used in the previous article. We saw there that we cannot rely on the default built-in function because we need a random function where we are able to control the seed to make sure we always get the same sequence of random values. So the seed value is also another variable that we can control to get a different blob shape. Go change that value manually and see the result.

In the previous article, I mentioned that the Paint API removes all of the complexity on the CSS side of things, and that gives us more flexibility to create complex animations. For example, we can combine what we have done up to this point with keyframes and cubic-bezier():

Live demo (Chrome and Edge only)

The demo includes another example using the parabolic curve I detailed in a previous article.

Controlling the movement of the points

In all the blobs we’ve created so far, we considered the same movement for our points. Whether we’re using the uniform configuration or the random one, we always move the points from the edge to the center of the circle following a line.

Now let’s see how we can control that movement in order to get even more animations. The idea behind this logic is simple: we move the x and y differently.

Previously we were doing this:

var x = Math.cos((i / N) * (2 * Math.PI)) * (Radius - F(B)) + CenterX;
var y = Math.sin((i / N) * (2 * Math.PI)) * (Radius - F(B)) + CenterY;

…where F(B) is a function based on the variable B that holds the transition.

Now we will have something like this instead:

var x = Math.cos((i / N) * (2 * Math.PI)) * (Radius - Fx(B)) + CenterX;
var y = Math.sin((i / N) * (2 * Math.PI)) * (Radius - Fy(B)) + CenterY;

…where we’ve updating the x and y variables differently to makes more animations. Let’s try a few.

One axis movement

For this one, we will make one of the functions equal to 0 and keep the other one the same as before. In other words, one coordinate remains fixed along the animation

If we do:

Fy(B) = 0

…we get:

A cursor hovers two circular images, which has points that pull inward from the left and right edges of the circle to created jagged sides along the circles.
Live demo (Chrome and Edge only)

The points are only moving horizontally to get another kind of effect. We can easily do the same for the other axis by making Fx(B)=0 (see a demo).

I think you get the idea. All we have to do is to adjust the functions for each axis to get a different animation.

Left or right movement

Let’s try another kind of movement. Instead of making the points converging into the center, let’s make them move into the same direction (either right or left). We need a condition based on the location of the point which is defined by the angle.

Illustration showing the blue outline of a circle with 8 points around the shape and thick red lines bisecting the circle to show the axes.

We have two group of points: ones in the [90deg 270deg] range (the left side), and the remaining points along the ride side of the shape. If we consider the indexes, we can express the range differently, like [0.25N 0.75N] where N is the number of points.

The trick is to have a different sign for each group:

var sign = 1;
if(i<0.75*N && i>0.25*N) 
  sign = -1; /* we invert the sign for the left group */
if(T == 0) 
  var r = RADIUS - B*sign*(i%2);
else 
  var r = RADIUS - B*sign*random();
var x = Math.cos((i / N) * (2 * Math.PI)) * r + cx;

And we get:

An animated gif showing a cursor entering the right side of a circular image, which has points the are pulled toward the center of the circle, then return once the cursor exits.
Live demo (Chrome and Edge only)

We are able to get the same direction but with one small drawback: one group of the points are going outside the mask area because we are increasing the distance on some points while decreasing the distance on others. We need to reduce the size of our circle to leave enough space for all of our points.

We simply decrease the size of our circle using the V value that defines the final value for our B variable. In other words, it’s the maximum distance that one point can reach.

Our initial shape (illustrated by the grey area and defined with the green points) will cover a smaller area since we will decrease the Radius value with the value of V:

const V = parseFloat(properties.get('--v'));
const RADIUS = size.width/2 - V;
Live demo (Chrome and Edge only)

We fixed the issue of the points getting outside but we have another small drawback: the hover-able area is the same, so the effect starts even before the cursor hits the image. It would be good if we can also reduce that area so everything is consistent.

We can use an extra wrapper and a negative margin trick. Here’s the demo. The trick is pretty simple:

.box {
  display: inline-block;
  border-radius: 50%;
  cursor: pointer;
  margin: calc(var(--v) * 1px);
  --t: 0;
}

img {
  display: block;
  margin: calc(var(--v) * -1px);
  pointer-events: none;
  -webkit-mask: paint(blob);
  --b: 0;
  transition:--b .5s;
}
.box:hover img {
  --b: var(--v)
}

The extra wrapper is an inline-block element. The image inside it has negative margins equal to the V variable which reduces the overall size of the shape’s box. Then we disable the hover effect on the image element (using pointer-events: none) so only the box element triggers the transition. Finally we add some margin to the box element to avoid any overlap.

Like the previous effect, this one can also be combined with cubic-bezier() and keyframes to get more cool animations. Below is an example using my sinusoidal curve for a wobbling effect on hover.

Live demo (Chrome and Edge only)

If we add some transforms, we can create a kind of strange (but pretty cool) sliding animation:

A circular image is distorted and slides from right to left on hover in this animated gif.
Live demo (Chrome and Edge only)

Circular movement

Let’s tackle another interesting movement that will allow us to create infinite and “realistic” blob animations. Instead of moving our points from one location to another, we will rotate them around an orbit to have a continuous movement.

The blue outline of a circle with ten green points along its edges. A gray arrow shows the circle's radius and assigns it to a point on the circle with a variable, r, that has a red circle around it showing its hover boundary.

The initial location of our points (in green) will become an orbit and the red circle is the path that our points will take. In other words, each point will rotate around its initial position following a circle having a radius r.

All we need to do is make sure there is no overlap between two adjacent paths so the radius need to have a maximum allowed value.

I will not detail the math but the max value is equal to:

const r = 2*Radius*Math.sin(Math.PI/(2*N));
A blobby shape moves in a circular motion around an image of a cougar's face.
Live demo (Chrome and Edge only)

This is the relevant part of the code:

var r = (size.width)*Math.sin(Math.PI/(N*2));
const RADIUS = size.width/2 - r;
// ...

for(var i = 0; i < N; i++) {
  var rr = r*random();
  var xx = rr*Math.cos(B * (2 * Math.PI));
  var yy = rr*Math.sin(B * (2 * Math.PI)); 
  var x = Math.cos((i / N) * (2 * Math.PI)) * RADIUS + xx + cx;
  var y = Math.sin((i / N) * (2 * Math.PI)) * RADIUS + yy + cy;
  point[i] = [x,y];
}

We get the max value of the radius and we reduce that value from the main radius. Remember that we need to have enough space for our points so we need to reduce the mask area like we did with the previous animation. Then for each point we get a random radius rr (between 0 and r). Then we calculate the position inside the circular path using xx and yy. And, finally, we place the path around its orbit and get the final position (the x, y values).

Notice the value B which is, as usual, the one with the transition. This time, we will have a transition from 0 to 1 in order to make a full turn around the orbit.

Spiral movement

One more for you! This one is a combination of the two previous ones.

We saw how to move the points around a fixed orbit and how to move a point from the edge of the circle to the center. We can combine both and have our point move around an orbit and we do the same for the orbit by moving it from the edge to the center.

Let’s add an extra variable to our existing code:

for(var i = 0; i < N; i++) {
  var rr = r*random();
  var xx = rr*Math.cos(B * (2 * Math.PI));
  var yy = rr*Math.sin(B * (2 * Math.PI)); 

  var ro = RADIUS - Bo*random();
  var x = Math.cos((i / N) * (2 * Math.PI)) * ro + xx + cx;
  var y = Math.sin((i / N) * (2 * Math.PI)) * ro + yy + cy;
  point[i] = [x,y];
}

As you can see, I used the exact same logic as the very first animation we looked at. We reduce the radius with a random value (controlled with Bo in this case).

A blob morphs shape as it moves around an image of a cougar's face.
Live demo (Chrome and Edge only)

Yet another fancy blob animation! Now each element has two animations: one animates the orbit (Bo), and the other animates the point in its circular path (B). Imagine all the effects that you can get by simply adjusting the animation value (duration, ease, etc.)!

Putting everything together

Oof, we are done with all the animations! I know that some of you may have gotten lost with all the variations and all the variables we introduced, but no worries! We will sum everything up right now and you will see that it’s easier than what might expect.

I want to also highlight that what I have done is not an exhaustive list of all the possible animations. I only tackled a few of them. We can define even more but the main purpose of this article is to understand the overall structure and be able to extend it as needed.

Let’s summarize what we have done and what are the main points:

  • The number of points (N): This variable is the one that controls the granularity of the blob’s shape. We define it in the CSS and it is later used to define the number of control points.
  • The type of movement (T): In almost all the animations we looked at, I always considered two kind of animations: a “uniform” animation and a “random” one. I am calling this the type of movement that we can control using the variable T set in the CSS. We will have somewhere in the code to do an if-else based on that T variable.
  • The random configuration: When dealing with random movement, we need to use our own random() function where we can control the seed in order to have the same random sequence for each element. The seed can also be considered a variable, one that generates different shapes.
  • The nature of movement: This is the path that the points take. We can have a lot of variations, for example:
    • From the edge of the circle to the center
    • A one axis movement (the x or y axis)
    • A circular movement
    • A spiral movement
    • and many others…

Like the type of movement, the nature of the movement can also be made conditional by introducing another variable, and there is no limit to what can be done here. All we have to do is to find the math formula to create another animation.

  • The animation variable (B): This is the CSS variable that contains the transition/animation. We generally apply a transition/animation from 0 to a certain value (defined in all the examples with the variable V). This variable is used to express the position of our points. Updating that variable logically updates the positions; hence the animations we get. In most cases, we only need to animate one variable, but we can have more based on the nature of the movement (like the spiral one where we used two variables).
  • The shape area: By default, our shape covers the entire element area, but we saw that some movement require the points to go outside the shape. That’s why we had to reduce the area. We generally do this by the maximum value of B (defined by V), or a different value based on the nature of the movement.

Our code is structured like this:

var point = []; 
/* The center of the element */
const cx = size.width/2;
const cy = size.height/2;
/* We read all of the CSS variables */
const N = parseInt(properties.get('--n')); /* number of points */
const T = parseInt(properties.get('--t')); /* type of movement  */
const Na = parseInt(properties.get('--na')); /* nature of movement  */
const B = parseFloat(properties.get('--b')); /* animation variable */
const V = parseInt(properties.get('--v'));  /* max value of B */
const seed = parseInt(properties.get('--seed')); /* the seed */
// ...

/* The radius of the shape */
const RADIUS = size.width/2 - A(V,T,Na);

/* Our random() function */
let random =  function() {
  // ...
}
/* we define the position of our points */
for(var i = 0; i < N; i++) {
   var x = Fx[N,T,Na](B) + cx;
   var y = Fy[N,T,Na](B) + cy;
   point[i] = [x,y];
}

/* We draw the shape, this part is always the same */
ctx.beginPath();
// ...
ctx.closePath();
/* We fill it with a solid color */
ctx.fillStyle = '#000';
ctx.fill();

As you can see, the code is not as complex as you might have expected. All the work is within those function Fx and Fy, which defines the movement based on N,T and Na. We also have the function A that reduces the size of the shape to prevent points overflowing the shape during the animation.

Let’s check the CSS:

@property --b {
  syntax: '<number>';
  inherits: false;
  initial-value: 0;
}

img {
  -webkit-mask:paint(blob);
  --n: 20;
  --t: 0;
  --na: 1;
  --v: 50;
  --seed: 125;
  --b: 0;
  transition: --b .5s;
}
img:hover {
  --b: var(--v);
}

I think the code is self-explanatory. You define the variables, apply the mask, and animate the B variable using either a transition or keyframes. That’s all!

I will end this article with a final demo where I put all the variations together. All you have to do is to play with the CSS variables


Exploring the CSS Paint API series:


The post Exploring the CSS Paint API: Blob Animation appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.

How to Create a Newsletter and Send Email Campaigns with Mailpost.io

This post is originally published on Designmodo: How to Create a Newsletter and Send Email Campaigns with Mailpost.io

How to Create a Newsletter and Send Email Campaigns with Mailpost.io

An email newsletter is a powerful tool that enables a website owner to share material and valuable information with their network of prospects, subscribers, and customers. Aside from engagement based on triggers and actions, it can automatically provide communication between …

For more information please contact Designmodo

How to Fix WooCommerce Not Sending Order Emails (The Easy Way)

Are you frustrated by your WooCommerce store not sending order emails?

When running an eCommerce store, you need to know that your customers will receive their receipts and any order update emails quickly and reliably.

In this article, we’ll show you the easy way to fix WooCommerce not sending order emails.

How to fix WooCommerce not sending order emails

What Causes WooCommerce Emails to Not Send?

If you are running an online store, then you rely on email to keep your business running smoothly.

You use email to welcome new customers and build your relationship with them. Emails are sent to confirm orders and follow up on abandoned shopping carts. And email is needed to let customers reset their passwords.

But all too often, we hear that eCommerce sellers have trouble with WooCommerce not sending emails.

Sometimes this happens because of issues in your WooCommerce settings. We’ll show you how to check those settings first.

Other times it’s a deeper issue with the way WordPress sends email. By default, WordPress sends emails through PHP mail. Unfortunately, not all WordPress hosting servers are correctly configured to use PHP mail.

Even when your emails are sent successfully, they may be incorrectly identified as spam. This means they could be automatically deleted without ever being seen.

The best way to make sure your emails are reliably delivered is to send them through an SMTP service.

We’ll show you how to set up an SMTP server later in this guide, but first, let’s make sure there isn’t a problem with your WooCommerce settings.

Check WooCommerce Email and Order Settings

The first thing to check is your WooCommerce settings for emails and orders. If one of your settings is wrong, then your order emails won’t be sent.

Check WooCommerce Email Settings

We’ll start by checking that your emails haven’t been accidentally deactivated. To do that, navigate to WooCommerce » Settings on the WordPress dashboard and then click on the Emails tab.

List of WooCommerce Emails

Here you’ll see a list of all the notification emails that WooCommerce will send. Some are sent to you and some to your customers. You’ll need to check the settings for each email.

Let’s start at the top and check the ‘New order’ email by clicking on the ‘Manage’ button on the right.

You’ll need to check two settings. First, make sure the email is enabled. Sometimes it is disabled accidentally, and the email won’t be sent if the box isn’t checked.

Make Sure the Email is Enabled

Second, you need to make sure that the recipient’s email address is correct. You’ll only find this setting for emails that will be sent to you. When an email is sent to the customer, the correct email address will be used automatically.

You can do the same for each type of email in the list. If everything looks good, then we need to check the status of each order where WooCommerce did not send an order email.

Check WooCommerce Payment Status

You’ll need to navigate to WooCommerce » Orders to check the status of recent orders. If you don’t yet have any orders, then you’ll want to create a test order and then come back.

Navigate to WooCommerce » Orders

If the order status is ‘Pending payment’ as in this example, then that explains why an email was not sent. By default, WooCommerce doesn’t send an order email for pending sales.

Pending orders are waiting for further action. Maybe the customer added something to their cart and then abandoned it. Or maybe the customer needs to complete a manual payment, such as a bank transfer.

But if the status is ‘Processing’, then there’s a problem. An email should have been sent to both you and the customer. If it didn’t arrive in the inbox, then most likely it was treated as spam.

That’s a common problem with WooCommerce and WordPress emails. The best way to solve that problem is to send your email using an SMTP server.

Fix WordPress Email Reliability with an SMTP Server Plugin

SMTP is the standard protocol for sending emails over the internet, but it isn’t what WordPress uses by default. Unfortunately, that often results in emails from WordPress being treated as spam.

Sending email through an SMTP server is more reliable because it uses proper authentication. Your customer’s email software will be confident that your emails are genuine, and they’re less likely to be moved to the junk folder.

WP Mail SMTP is the best SMTP plugin for WordPress and WooCommerce. It’s the easiest way to make sure your order emails are actually delivered to your customer’s inbox.

To fix WooCommerce not sending order emails, you’ll need to install and activate the WP Mail SMTP plugin. You can check out our guide on how to install a WordPress plugin for more details.

Note: The free version of WP Mail SMTP is all that’s required for this tutorial. But the Elite plan includes White Glove Setup where an expert will set up the plugin for you.

On activation, the WP Mail SMTP setup wizard will start automatically. You’ll need to click on the Let’s Get Started button.

The WP Mail SMTP Setup Wizard Will Start Automatically

Next, you need to choose the SMTP service you wish to use. We recommend SMTP.com and Sendinblue because they are able to securely send large numbers of emails and without triggering spam filters.

Plus, Sendinblue lets you send up to 300 emails each day for free.

Choose Your SMTP Mailer Service

Once you’ve selected a service, you need to click on the ‘Save and Continue’ button. After that, you’ll be asked to configure your mailer settings.

Here you’ll be asked to copy some information from the mailer service you selected, and then paste it into the form. The exact steps you need to take will depend on the mailer service you have chosen.

Configure Your Mailer Settings

Note: If you’d prefer to bypass the wizard and set up WP Mail SMTP manually, then you’ll find manual step by step instructions in our ultimate guide on how to set up WP Mail SMTP with any SMTP service.

The setup wizard will also ask you to set up a From Email. Make sure you use the same business email address here as you entered when setting up your SMTP mailing service.

We Recommend You Force the Same Email Address

We also recommend that you check the ‘Force From Email’ box. This will make sure you use the same email address across your website. This can also help to make sure your WooCommerce emails don’t go to spam.

You’ll then be asked which email features you wish to enable. You need ‘Improved Email Deliverability’ and ‘Email Error Tracking’ to fix WooCommerce not sending email. They will be selected by default.

Enable WP Mail SMTP Email Features

If you’ve purchase WP Mail SMTP Pro, then you’ll have access to a few additional features. For example, the ‘Detailed Email Logs’ feature will let you check individual emails to make sure they being are sent.

WP Mail SMTP Pro Offers Additional Features

The Pro version will also let you resend a failed email. That can be really helpful when the customer typed in the wrong email address.

Send a Test Email

Congratulations, you’ve now set everything up! Let’s make sure it works by sending a test email.

You’ll need to navigate to WP Mail SMTP » Tools and then click on the ‘Email Test’ tab. The site’s admin email will be entered by default, but you can send the test email to a different address if you like. Next, click ‘Send Email’.

Make Sure Everything Works by Sending a Test Email

If everything has been set up correctly, then you should see a ‘Success!’ message. Make sure you also visit your email inbox to make sure the email actually arrived.

You Should See a Success! Message

We hope this tutorial helped you learn how to fix WooCommerce not sending order emails.

You may also want to learn the right way to create an email newsletter or check out list of must have WooCommerce plugins to grow your store.

If you liked this guide, then please consider subscribing to our YouTube Channel for WordPress video tutorials. You can also find us on Twitter and Facebook.

The post How to Fix WooCommerce Not Sending Order Emails (The Easy Way) appeared first on WPBeginner.

Refactoring CSS: Optimizing Size And Performance (Part 3)

In previous articles from this series, we’ve covered auditing CSS codebase health and the incremental CSS refactoring strategy, testing, and maintenance. Regardless of how much the CSS codebase has been improved during the refactoring process and how much more maintainable and extendable it is, the final stylesheet needs to be optimized for the best possible performance and least possible file size.

Deploying the refactored codebase shouldn’t result in worse website performance and worse user experience. After all, users won’t wait around forever for the website to load. Also, the management will be dissatisfied with the decreased traffic and revenue caused by the unoptimized codebase, despite the code quality improvements.

In this article, we’re going to cover CSS optimization strategies that can optimize CSS file size, loading times, and render performance. That way, the refactored CSS codebase is not only more maintainable and extensible but also performant and checks all boxes that are important both to the end-user and management.

Part Of: CSS Refactoring

Optimizing Stylesheet File Size

Optimizing file size boils down to removing unnecessary characters and formatting and optimizing the CSS code to use different syntax or shorthand properties to reduce the overall number of characters in a file.

Optimization And Minification

CSS optimization and minification have been around for years and became a staple in frontend optimization. Tools like cssnano and clean-css are among my favorite tools when it comes to CSS optimization and minification. They offer a wide variety of customization options to further control how code is being optimized and which browsers are supported.

These tools work in a similar way. First, the unoptimized code is parsed and transpiled following the rules set in the config. The result is the code that uses fewer characters but still retains the formatting (line breaks and whitespaces).

/* Before - original and unoptimized code */
.container {
  padding: 24px 16px 24px 16px;
  background: #222222;
}

/* After - optimized code with formatting */
.container {
  padding: 24px 16px;
  background: #222;
}

And finally, the transpiled optimized code is minified by removing all unnecessary text formatting. Depending on the codebase and supported browsers set in the config, code with deprecated vendor prefixes can also get removed.

/* Before - optimized code with formatting */
.container {
  padding: 24px 16px;
  background: #222;
}

/* After - optimized and minified code */
.container{padding:24px 16px;background:#222}

Even in this basic example, we’ve managed to reduce the overall file size from 76 bytes to 55 bytes, resulting in a 23% reduction. Depending on the codebase and the optimization tools and config, CSS optimization and minification can be even more effective.

CSS optimization and minification can be considered as an easy win due to the significant payoff with just a few tweaks to the CSS workflow. That is why minification should be treated as the bare minimum performance optimization and a requirement for all stylesheets on the project.

Optimizing Media Queries

When we write media queries in CSS, especially when using multiple files (PostCSS or Sass), we usually don’t nest the code under a single media query for an entire project. For improved maintainability, modularity, and code structure, we usually write the same media query expressions for multiple CSS components.

Let’s consider the following example of an unoptimized CSS codebase.

.page {
  display: grid;
  grid-gap: 16px;
}

@media (min-width: 768px) {
  .page {
    grid-template-columns: 268px auto;
    grid-gap: 24px;
  }
}

/* ... */

.products-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  grid-gap: 16px;
}

@media (min-width: 768px) {
  .products-grid {
    grid-template-columns: repeat(3, 1fr);
    grid-gap: 20px;
  }
}

As you can see, we have a repeated @media (min-width: 768px) per component for better readability and maintenance. Let’s run the optimization and minification on this code example and see what we get.

.page{display:grid;grid-gap:16px}@media (min-width: 768px){.page{grid-template-columns:268px auto;grid-gap:24px}}.products-grid{display:grid;grid-template-columns:repeat(2,1fr);grid-gap:16px}@media (min-width: 768px){.products-grid{grid-template-columns:repeat(3,1fr);grid-gap:20px}}

This might be a bit difficult to read, but all we have to notice is the repeated @media (min-width: 768px) media query. We’ve already concluded that we want to reduce the number of characters in a stylesheet and we can nest multiple selectors under a single media query, so why didn’t the minifier removed the duplicated expression? There is a simple reason for that.

Rule order matters in CSS, so to merge the duplicated media queries, code blocks need to be moved. This will result in rule orders being changed which can cause unwanted side-effects in styles.

However, combining media queries could potentially make the file size even smaller, depending on the codebase and structure. Tools and packages like postcss-sort-media-queries allow us to remove duplicated media queries and further reduce the file size.

Of course, there is the important caveat of having a well-structured CSS codebase structure that doesn’t depend on the rule order. This optimization should be taken into account when planning the CSS refactor and establishing ground rules.

I would recommend first checking if the optimization benefit outweighs the potential risks. This can be easily done by running a CSS audit and checking media query stats. If it does, I would recommend adding it later on and running automated regression testing to catch any unexpected side-effects and bugs that can happen as a result.

Removing Unused CSS

During the refactoring process, there is always a possibility that you’ll end up with some unused legacy styles that haven’t been completely removed or you’ll have some newly added styles that are not being used. These styles also add to the overall character count and the file size. Eliminating these unused styles using automated tools, however, can be somewhat risky because the tools cannot accurately predict which styles are actually used.

Tools like purgecss go through all the files in the project and use all the classes mentioned in files as selectors, just to err on the side of caution and not accidentally delete selectors for dynamic, JavaScript-injected elements, among other potential cases. However, purgecss offers flexible config options as workarounds for these potential issues and risks.

However, this improvement should be done only when the potential benefits outweigh the risks. Additionally, this optimization technique will require considerable time to set up, configure and test, and might cause unintended issues down the line, so proceed with caution and make sure that the setup is bulletproof.

Eliminating Render-Blocking CSS

By default, CSS is a render-blocking resource, meaning that the website won’t be displayed to the user until all linked stylesheets and their dependencies (fonts, for example) have been downloaded and parsed by the browser.

If the stylesheet file has a large file size or multiple dependencies which are located on third-party servers or CDNs, website rendering can be delayed significantly depending on the network speed and reliability.

Largest Contentful Paint (LCP) has become an important metric in the last few months. LCP is not only important for performance but also SEO — websites with better LCP scores will have better search results ranking. Removing render-blocking resources like CSS is one way of improving the LCP score.

However, if we would defer the stylesheet loading and processing, this would result in Flash Of Unstyled Content (FOUC) — content would be displayed to the user right away and styles would be loaded and applied a few moments later. This switch could look jarring and it may even confuse some users.

Critical CSS

With Critical CSS, we can ensure that the website loads with the minimum amount of styles which are guaranteed to be used on the page when it’s initially rendered. This way, we can make the FOUC much less noticeable or even eliminate it for most cases. For example, if the homepage features a header component with navigation and a hero component located above-the-fold, this means that the critical CSS will contain all the necessary global and component styles for these components, while styles for other components on the page will be deferred.

This CSS is inlined in HTML under a style tag, so the styles are loaded and parsed alongside the HTML file. Although this will result in a slightly larger HTML file size (which should also be minified), all other non-critical CSS will be deferred and won’t be loaded right away and the website will render faster. All in all, the benefits outweigh the increase in the HTML file size.

<head>
  <style type="text/css"><!-- Minified Critical CSS markup --></style>
</head>

There are many automated tools and NPM packages out there, depending on your setup, that can extract critical CSS and generate deferred stylesheets.

Deferring Stylesheets

How exactly do we make the CSS to be non-blocking? We know that it shouldn’t be referenced in the HTML head element when the page HTML is first downloaded. Demian Renzulli has outlined this method in his article.

There is no native HTML approach (as of yet) to optimize or defer the loading of render-blocking resources, so we need to use JavaScript to insert the non-critical stylesheet into the HTML markup after the initial render. We also need to make sure that these styles get loaded in the non-optimal (render-blocking) way if a user is visiting the page with JavaScript not enabled in the browser.

<!-- Deferred stylesheet -->
<link rel="preload" as="style" href="path/to/stylesheet.css" onload="this.onload=null;this.rel='stylesheet'">

<!-- Fallback -->
<noscript>
  <link rel="stylesheet" href="path/to/stylesheet.css">
</noscript>

With link rel="preload" as="style" makes sure that the stylesheet file is requested asynchronously, while onload JavaScript handler makes sure that the file is loaded and processed by the browser after the HTML document has finished loading. Some cleanup is needed, so we need to set the onload to null to avoid this function running multiple times and causing unnecessary re-renders.

This is exactly how Smashing Magazine handles its stylesheets. Each template (homepage, article categories, article pages, etc.) has a template-specific critical CSS inlined inside HTML style tag in the head element, and a deferred main.css stylesheet which contains all non-critical styles.

However, instead of toggling the rel parameter, here we can see the media query being switched from the automatically deferred low-priority print media to the high-priority all attribute when the page has finished loading. This is an alternative, equally viable approach to defer loading of non-critical stylesheets.

<link href="/css/main.css" media="print" onload="this.media='all'" rel="stylesheet">

Splitting And Conditionally Loading Stylesheets With Media Queries

For the cases when the final stylesheet file has a large file size even after the aforementioned optimizations have been applied, you could split the stylesheets into multiple files based on media queries and use media property on stylesheets referenced in the link HTML element to load them conditionally.

<link href="print.css" rel="stylesheet" media="print">
<link href="mobile.css" rel="stylesheet" media="all">
<link href="tablet.css" rel="stylesheet" media="screen and (min-width: 768px)">
<link href="desktop.css" rel="stylesheet" media="screen and (min-width: 1366px)">

That way, if a mobile-first approach is used, styles for larger screen sizes won’t be downloaded or parsed on mobile devices that could be running on slower or unreliable networks.

Just to reiterate, this method should be used if the result of the previously mentioned optimization methods results in a stylesheet with suboptimal file size. For regular cases, this optimization method won’t be as effective or impactful, depending on the individual stylesheet size.

Deferring Font Files And Stylesheets

Deferring font stylesheets (Google Font files, for example) could also be beneficial for initial render performance. We’ve concluded that stylesheets are render-blocking, but so are the font files that are referenced in the stylesheet. Font files also add quite a bit of overhead to the initial render performance.

Loading font stylesheets and font files is a complex topic and diving into it would take a whole new article just to explain all viable approaches. Luckily, Zach Leatherman has outlined many viable strategies in this awesome comprehensive guide and summarized the pros and cons of each approach. If you use Google Fonts, Harry Roberts has outlined a strategy for the fastest loading of Google Fonts.

If you decide on deferring font stylesheets, you’ll end up with Flash of Unstyled Text (FOUT). The page will initially be rendered with the fallback font until the deferred font files and stylesheets have been downloaded and parsed, at which point the new styles will be applied. This change can be very noticeable and can cause layout shifts and confuse users, depending on the individual case.

Barry Pollard has outlined some strategies that can help us deal with FOUT and talked about the upcoming size-adjust CSS feature which will provide an easier, more native way of dealing with FOUT.

Server-Side Optimizations

HTTP Compression

In addition to minification and file-size optimization, static assets like HTML, CSS files, JavaScript files, etc. HTTP compression algorithms like Gzip and Brotli can be used to additionally reduce the downloaded file size.

HTTP compression needs to be configured on the server which depends on the tech stack and config. However, performance benefits may vary and may not have as much impact as standard stylesheet minification and optimization, as the browsers will still decompress the compressed files and have to parse them.

Caching Stylesheets

Caching static files is a useful optimization strategy. Browsers will still have to download the static files from the server on the first load, but once they get cached they’ll be loaded from it directly on subsequent requests, speeding up the loading process.

Caching can be controlled via Cache-Control HTTP header at the server level (for example, using the .htaccess file on an Apache server).

With max-age we can indicate how long the file should stay cached (in seconds) in the browser and with public, we are indicating that the file can be cached by the browser and any other caches.

 Cache-Control: public, max-age=604800

A more aggressive and effective cache strategy for static assets can be achieved with immutable config. This tells the browser that this particular file will never change and that any new updates will result in this file getting deleted and a new file with a different file name will take its place. This is known as cache-busting.

Cache-Control: public, max-age=604800, immutable

Without a proper cache-busting strategy, there is a risk of losing control over files that get cached on the user’s browser. Meaning that if the file were to change, the browser won’t be able to know that it should download the updated file and not use the outdated cached file. And from that point on, there is virtually nothing we can do to fix that and the user will be stuck with the outdated file until it expires.

For stylesheets, that could mean that if we were to update HTML files with new content and components that require new styling, these styles won’t display because the outdated stylesheet is cached without a cache-busting strategy and the browser won’t know that it has to download the new file.

Before using a caching strategy for stylesheets or any other static files, effective cache-busting mechanisms should be implemented to prevent outdated static files from getting stuck in the user’s cache. You can use one of the following versioning mechanisms for cache-busting:

  • Appending a query string to the file name.
    For example styles.css?v=1.0.1. However, some CDNs can completely ignore or strip the query string from the file name and resulting in the file getting stuck in the user’s cache and never updating.
  • Changing the file name or appending a hash.
    For example styles.a1bc2.css or styles.v1.0.1.css. This is more reliable and effective than appending a query string to the file name.

CDN Or Self-hosting?

Content Delivery Network (CDN) is a group of geographically distributed servers that are commonly used for the reliable and fast delivery of static assets like images, videos, HTML files, CSS files, JavaScript files, etc.

Although CDNs might seem like a great alternative to self-hosting static assets, Harry Roberts has done in-depth research on the topic and concluded that self-hosting assets are more beneficial for performance.

“There really is very little reason to leave your static assets on anyone else’s infrastructure. The perceived benefits are often a myth, and even if they weren’t, the trade-offs simply aren’t worth it. Loading assets from multiple origins is demonstrably slower.”

That being said, I would recommend self-hosting the stylesheets (font stylesheets included, if possible) by default and moving to CDN only if there are viable reasons or other benefits to doing so.

Auditing CSS File Size and Performance

WebPageTest and other similar performance auditing tools can be used to get a detailed overview of the website loading process, file sizes, render-blocking resources, etc. These tools can give you an insight into how your website loads on a wide range of devices — from a desktop PC running on a high-speed network to low-end smartphones running on slow and unreliable networks.

Let’s do a performance audit on a website mentioned in the first article from this series — the one with the 2MB of minified CSS.

First, we’ll take a look at the content breakdown to determine which resources take up the most bandwidth. From the following charts, we can see that the images take up most requests, meaning that they need to be lazy-loaded. From the second chart, we can see that stylesheets and JavaScript files are the largest in terms of file size. This is a good indication that these files need to either be minified and optimized, refactored, or split into multiple files and loaded asynchronously.

We can draw even more conclusions from the Web Vitals charts. By taking a look a the Largest Contentful Paint (LCP) chart, we can get a detailed overview of render-blocking resources and how much they affect the initial render.

We could already conclude that the website stylesheet will have the most impact on the LCP and loading stats. However, we can see font stylesheets, JavaScript files, and images referenced inside the stylesheets that are also render-blocking. Knowing that we can apply the aforementioned optimization methods to reduce the LCP time by eliminating render-blocking resources.

Conclusion

The refactoring process isn’t complete when the code health and quality have been improved and when codebase weaknesses and issues have been fixed. Refactored codebase should result in the same or improved performance compared to the legacy codebase.

End users shouldn’t experience performance issues or long loading times from the refactored codebase. Luckily, there are many methods out there to make sure that the codebases are both robust and performant — from the simple minification and optimization methods to the more complex methods like eliminating render-blocking resources and code-splitting.

We can use various performance auditing tools like WebPageTest to get a detailed overview of loading times, performance, render-blocking resources, and other factors so we can address these issues early and effectively.

Part Of: CSS Refactoring

References

What makes good website feedback and how do you get it from your clients?

If you’ve designed and built a website for someone else, then you know the feeling of dread that can surround feedback time. Multiple emails from multiple clients with subject lines that read a bit like Re:Fwd:Website feedback due three days ago, which may or may not have the same feedback or bugs reported as the very similar email from yesterday. It’s enough to give you a headache, and that’s before you’ve even opened the emails to see vague feedback like “I don’t think this pops enough” or “there’s a bit on the page that looks odd”.

So, what makes good website feedback?

Good website feedback is clear, actionable and trackable. Let’s break those down a little more.

Clear

Good feedback makes it obvious what is wrong and what needs to be fixed. It contains information that makes it easy for someone else to see and understand what you are referring to. Vague feedback like “I don’t really like this colour” is less helpful to the recipient than “This is not our brand shade of blue, please use the brand colour.”

Actionable

Good feedback makes it easy for the receiver to do something with it. It contains information that helps the receiver to decide what’s wrong and how to fix it.  

Trackable

Emails can easily get lost in a jumble of similar sounding subject lines, or worse, completely overlooked in the back and forth communication. Tracking feedback shouldn’t be difficult or stressful.

How do you give good feedback? What information do you need to include?

Giving feedback doesn’t need to be difficult. Providing good feedback means that it will be actioned faster too. 

Here’s a handy checklist when giving feedback to make sure it’s great. Not all the information will need to be included all the time, but it will definitely help. 

1. Break feedback into small pieces. 

Don’t load up with multiple bits of feedback at the same time. Break it into smaller sections. Keep it simple, people!

2. What part of the page is the feedback referring to?

Include the URL of the page you’re referring to.

3. Include a screenshot or screen recording with feedback

If a picture is worth 100 words, including a screenshot or screen recording may prove easier than trying to explain what you’re experiencing or referring to.

4. Don’t forget the technical information

Include information such as your operating system. What browser you are using for websites and web applications. Include whether you were using a desktop or mobile, if it’s not already clear.

5. For feedback on actions, include what you were doing when it happened.

If your feedback refers to a bug or problem with the website, include the “steps to recreate” the problem. When a bug is replicable (able to be recreated) it’s easier to work out what went wrong and to fix it.

6. Include any error messages and codes you received

If you’re getting a specific error message or code, it will be helpful when pinpointing if there’s a bug and how to resolve it. 

7. Can you replicate the issue? 

Does the same thing happen every time you do something? This information is super helpful to developers for fixing any issues.

8. How urgent is it that this is changed?

On a website, does the feedback refer to something broken, is it cosmetic, does it affect how people use the website?

All these things help to determine the severity and help prioritise the order that feedback is actioned.  

Typically severity varies from Very High (it stops you from working completely) down to Very Low (cosmetic changes). 

What can I do to help get better feedback? (Solutions)

  • Keep relying on email
  • Switch to Spreadsheets to help keep track of tasks
  • Use a feedback tool like BugHerd.

How does Bugherd help?

A tool like BugHerd can help a lot with making feedback from clients clear, actionable and manageable.

To begin, BugHerd can do a lot of the work in making feedback clearer. BugHerd pins feedback to a webpage, captures the technical information and helps clarify feedback. Here’s an example of how BugHerd organises information for a feedback task.

A – What is wrong and what it should be

B – URL (location)

C – Operating system, technical information for replicating and solving

D – Screenshot

E – Severity

F – Additional information

Feedback is pinned to a website, so you know exactly what each piece of feedback is referring to on the site. In cases where further clarification is required, BugHerd makes it easy to comment on a task and request more information from the person leaving the feedback.

Managing feedback is one of the toughest parts of handling client feedback.

With BugHerd, all feedback is sent to one central location – a kanban style board. Here you can track feedback until it’s completed, assign tasks to team members, communicate with clients and ensure every piece of feedback is dealt with.

The post What makes good website feedback and how do you get it from your clients? appeared first on Codrops.

PolkitErrorTextual Authentication Agent

How to fix the following polkit error:

***Error creating textual authentication agent: Error opening current controlling terminal for the process (`/dev/tty'): No such device or address (polkit-error-quark, 0)