Conjuring Generative Blobs With The CSS Paint API

The CSS Paint API (part of the magical Houdini family) opens the door to an exciting new world of design in CSS. Using the Paint API, we can create custom shapes, intricate patterns, and beautiful animations — all with a touch of randomness — in a way that is portable, fast, and responsive.

We are going to dip our toes into the bubbling cauldron of generative CSS magic by creating my favorite shape, the blob. Random blobs are a great starting point for anyone new to generative art/design, and we will be learning the CSS Paint API as we go, so this is an ideal starting point for folks who are new to this world. You’ll be a generative CSS magician in no time!

Let’s hop on our broomsticks and conjure up some shapes.

Generative?

For some folks reading this, generative art may be an unfamiliar topic. If you are already comfortable with generative art/design, feel free to hop down to the next section. If not, here’s a little example:

Imagine, for a moment, that you are sitting at a desk. You have three stamps, some dice, and a piece of paper. Each of the stamps has a different shape on it. There is a square, a line, and a circle. You roll the dice. If the dice land on one, you use the square stamp on the page. If the dice lands on two, you use the line stamp. If it lands on three, you use the circle stamp. If the dice reads four, five, or six, you do nothing. You repeat the roll-and-stamp process until the page fills with shapes — this is generative art!

It can seem a little scary at first, but really, that’s all “generative” means — something created with an element of chance/unpredictability. We define some rules and let a source of randomness guide us to an outcome. In the “analog” example above, the randomness source is some dice. When we are working in the browser, it could be Math.random() or another similar function.

To bring things back to the land of ones and zeros for a moment, this is what the above example would look like if written in code:

Pretty cool, eh? By defining some simple rules and actioning them at random, we have created a unique pattern. In this tutorial series, we will use generative techniques just like this to create exciting user interfaces.

What is the CSS Paint API, and what’s a worklet?

The CSS Paint API allows us low-level access to CSS itself(!) through an HTML5 <canvas>-like drawing API. We can harness this power with something called a worklet.

Worklets, in short, are JavaScript classes. Each worklet class must have a paint() function. A worklet’s paint() function can programmatically create an image for any CSS property that expects one.

For example:

.my-element {
  background-image: paint(texture);
}

Here, we have a fictional texture worklet that generates a beautiful (I’ll leave this up to your imagination), programmatic texture. Where we might usually assign a url(...) value to the background-image property, we instead call paint(worklet_name) — this runs the worklet’s paint() function and renders the output to the target element.

We will be getting into how to write worklets in detail shortly, but I wanted to give you a quick primer on what they are before I start talking about them.

What we are building

So, in this tutorial, we will be building a generative blob worklet. Our worklet will take a few input parameters (as CSS Custom Properties, more on this a little later) and return a beautiful, random blob shape.

Let’s get started by checking out some examples of the finished worklet in action — if a picture paints a thousand words, a CodePen must paint a million, right?

The blob worklet, as a background image

First, here’s a demo of the blob worklet just hanging out on its own, generating a value for the background-image property of an element:

I encourage you to look at the CSS for the above CodePen, change the custom properties, resize the element, and see what happens. See how the shape resizes fluidly and updates when the custom properties change? Don’t worry about understanding how this works right now. At this stage, we are only concerned with what we are building.

Generative image masks, a practical use case

Awesome, now that we have seen the “standalone” worklet, let’s check out how we can use it. In this example, the worklet functions as a generative image mask:

The result (I think) is rather striking. The worklet adds a natural, eye-catching curve to the design. In addition, the mask shape is different each time the page loads, which is a fantastic way to keep the UI fresh and exciting — click “rerun” on the CodePen above to see this effect in action. This ever-changing behavior is subtle, for sure, but I hope it will bring folks who notice it a little bit of joy. The web can be quite a cold, sterile place, and generative touches like this can make it feel a lot more organic!

Note: I’m certainly not suggesting we all start making our entire interfaces change at random. That would be terrible for usability! This kind of behavior works best when applied sparingly and only to presentational elements of your website or app. Think blog post headers, hero images, subtle background patterns, etc.

Now, this is just one example (and simple one, at that), but I hope it gives you some ideas on how you could use the blob worklet in your own design and development. For anyone looking for some extra inspiration, a quick Dribbble search for “blobs” should give you a whole heap of ideas!

Wait, do I need the CSS Paint API to make blobs?

In short, no!

There are, in fact, a plethora of ways to make blobs to use in your UI design. You could reach for a tool like Blobmaker, do some magic with border-radius, use a regular <canvas> element, whatever! There are tons of roads leading to blob city.

None of these, however, are quite the same as using the CSS Paint API. Why?

Well, to name a few reasons…

It allows us to be expressive in our CSS

Instead of dragging around sliders, tweaking radii, or endlessly clicking “regenerate” in the hope that a perfect blob comes our way, we can use just a few human-readable values to get what we need.

For example, the blob worklet we will be building in this tutorial takes the following input properties:

.worklet-target {
  --blob-seed: 123456;
  --blob-num-points: 8;
  --blob-variance: 0.375;
  --blob-smoothness: 1;
  --blob-fill: #000;
}

Need your blobs to be super subtle and minimal? Reduce the --blob-variance custom property. Need them to be detailed and overstated? Bring it up!

Fancy redesigning your site in a more brutalist direction? No problem! Instead of re-exporting hundreds of assets or custom coding a bunch of border-radius properties, simply reduce the --blob-smoothness custom property to zero:

Handy, eh? The CSS Paint API, through worklets, allows us to create ever-unique UI elements that fit right in with a design system.

Note: I am using GSAP in the examples above to animate the input properties of the paint worklet we are building in this tutorial.

It is super performant

It just so happens that generative work can get a little heavy, computation-wise. We often find ourselves looping through lots of elements, performing calculations, and other fun stuff. When we factor in that we may need to create multiple programmatic, generative visuals on a page, performance issues could become a risk.

Luckily for us, CSS Paint API worklets do all their magic outside of the main browser thread. The main browser thread is where all of the JavaScript we usually write exists and executes. Writing code this way is perfectly OK (and generally preferable), **but it can have limitations. When we try and do too much on the main browser thread, the can UI become sluggish or even blocked.

As worklets run on a different thread to the main website or app, they will not “block” or slow down the interface. Additionally, this means that the browser can spin up lots of separate worklet instances that it can call on when needed — this is similar to containerization and results in blazing fast performance!

It won’t clutter the DOM

Because the CSS Paint API essentially adds an image to a CSS property, it doesn’t add any extra elements to the DOM. To me, this feels like a super clean approach to creating generative visual elements. Your HTML structure remains clear, semantic, and unpolluted, while your CSS handles how things look.

Browser support

It is worth noting that the CSS Paint API is a relatively new technology, and although support is growing, it is still unavailable in some major browsers. Here is a browser support table:

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

Desktop

ChromeFirefoxIEEdgeSafari
65NoNo79No

Mobile / Tablet

Android ChromeAndroid FirefoxAndroidiOS Safari
92No92No

Although browser support is still a little thin on the ground — in this tutorial, we will be looking at how to use the css-paint-polyfill maintained by GoogleChromeLabs to make sure users in all browsers can enjoy our creations.

We will, additionally, be looking at how to “fail gracefully” when the CSS Paint API is unsupported. A polyfill means extra JavaScript weight, so for some folks, it is not a viable solution. If this is you, don’t worry. We will be exploring browser support options for everyone.

Let’s code!

OK, OK! We know what we are building and why the CSS Paint API rocks — now let’s get coding! First things first, let’s get a development environment spun up.

Note: if you get a little lost at any point during in this tutorial, you can view a finished version of the worklet.

A simple development environment

To get us started, I have created a worklet-starter-kit repository. As a first step, pop on over to GitHub and clone it. Once you have cloned and navigated inside the repo, run:

npm install

Followed by:

npm run start

Once you have run the above commands, a simple development server fires up in the current directory, and your default browser opens. As worklets must be loaded either over HTTPS or from localhost — this setup ensures that we can use our worklet without any CORS issues. The starter kit also handles automatically refreshing the browser when we make any changes.

As well as serving our content and providing a basic live reload, this repository features a simple build step. Powered by esbuild, this process bundles up any JavaScript imports inside our worklet and outputs the result to a worklet.bundle.js file. Any changes made in worklet.js are automatically reflected in worklet.bundle.js.

If you have a poke around the repository, you might notice that there is already some HTML and CSS kicking around. We have a simple index.html file with a single worklet-canvas div, alongside some CSS to center it on the page and scale it to the viewport. Think of this as a blank canvas for all of your worklet experimentation!

Initializing our worklet

OK, now that we have our development environment up and running, it’s time to create our worklet. Let’s start by navigating to the worklet.js file.

Note: Remember, worklet.bundle.js is automatically generated by our build step. We don’t ever want to edit this file directly.

In our worklet.js file, we can define our Blob class and register it with the registerPaint function. We pass two values to registerPaint — the name we would like our worklet to have (in our case, blob) and the class that defines it:

class Blob {}

registerPaint("blob", Blob);

Excellent! We just took the first step towards creating our blobs!

Adding a paint() function

Now, not much is happening yet, so let’s add a simple paint() function to our Blob class to check things are working OK:

paint(ctx, geometry, properties) {
  console.log(`Element size is ${geometry.width}x${geometry.height}`);

  ctx.fillStyle = "tomato";
  ctx.fillRect(0, 0, geometry.width, geometry.height);
}

We can think of this paint() function like a callback. It runs, initially, when the worklet’s target element first renders. After this, any time the element’s dimensions change or the worklet’s input properties update, it runs again.

When the paint() function is called, it automatically has a few values passed through it. In this tutorial, we are making use of the first three:

  1. context — a 2D drawing context similar to that of a <canvas> element, we use this to draw things.
  2. geometry — an object containing the width and height of the target element
  3. properties — an array of custom properties

Now that we have a simple paint() function defined, let’s pop over to the index.html file and load our worklet. To do so, we are going to add a new <script> just before our closing </body> tag:

<script>
  if (CSS["paintWorklet"] !== undefined) {
    CSS.paintWorklet.addModule("./worklet.bundle.js");
  }
</script>

Note: we are registering the bundled version of our worklet!

Excellent. Our blob worklet is now loaded and ready for use in our CSS. Let’s use it to generate a background-image for our worklet-canvas class:

.worklet-canvas {
  background-image: paint(blob);
}

Once you have added the above snippet, you should see a red square. Our worklet is alive! Nice work. If you resize the browser window, you should see the worklet-canvas element’s dimensions printed in the browser console. Remember, the paint() function runs whenever the worklet target’s dimensions change.

Defining the worklet’s input properties

To allow our worklet to generate beautiful blobs, we need to help it out and pass it some properties. The properties we need are:

  • --blob-seed — a “seed” value for a pseudorandom number generator; more on this in a moment
  • --blob-num-points — how detailed the blob is based on the number of points used along the shape
  • --blob-variance — how varied the blob’s control points are
  • --blob-smoothness — the smoothness/sharpness of the blob’s edges
  • --blob-fill — the blob’s fill color

Let’s tell our worklet that it will receive these properties and that it needs to watch them for changes. To do so, we can head back over to our Blob class and add an inputProperties getter:

static get inputProperties() {
  return [
    "--blob-seed",
    "--blob-num-points",
    "--blob-variance",
    "--blob-smoothness",
    "--blob-fill",
  ];
}

Cool. Now that our worklet knows what input properties to expect, we should add them to our CSS:

.worklet-canvas {
  --blob-seed: 123456;
  --blob-num-points: 8;
  --blob-variance: 0.375;
  --blob-smoothness: 1;
  --blob-fill: #000;
}

Now, at this point, we could use the CSS Properties and Values API (another member of the Houdini family) **to assign some defaults and make these custom properties a little easier to parse in our worklet. Unfortunately, however, at this moment, the Properties and Values API does not have the best browser support.

For now, to keep things simple, we are going to leave our custom properties as they are — relying on some basic parsing functions in our worklet instead.

Heading back to our worklet class for a moment, let’s add these utility functions:

propToString(prop) {
  return prop.toString().trim();
}

propToNumber(prop) {
  return parseFloat(prop);
}

In the absence of the Properties and Values API, these simple utility functions will help us convert the properties passed to paint() to usable values.

Using our new helper functions, we can parse properties and define some variables to use in our paint() function. Let’s remove the old “debug” code, too:

paint(ctx, geometry, properties) {
  const seed = this.propToNumber(properties.get("--blob-seed"));
  const numPoints = this.propToNumber(properties.get("--blob-num-points"));
  const variance = this.propToNumber(properties.get("--blob-variance"));
  const smoothness = this.propToNumber(properties.get("--blob-smoothness"));
  const fill = this.propToString(properties.get("--blob-fill"));
}

If you log any of these variables, you should see that the properties made available by the paint() function map exactly to the Custom Properties we defined in our CSS a moment ago.

If you open up dev-tools, inspect the worklet-canvas element, and change any of these custom properties — you should see that the logs re-run and reflect the updated value. Why? Our worklet reacts to any changes to its input properties and re-runs its paint() function when it detects them.

OK, folks, it’s time to start forming our blob shape. To do this, we need a way of generating random numbers. After all, this is what will make our blobs generative!

Now, you may be thinking, “Hey, we can use Math.random() for this!” and in many ways, you would be right on. There is, however, a problem with using a “regular” random number generator in CSS Paint API worklets. Let’s check it out.

The problem with Math.random()

We noticed earlier how a worklet’s paint() function runs rather often. If we use a method such as Math.random() to generate random values within paint() — they will be different each time the function executes. Different random numbers mean a different visual result every time the worklet re-renders. We do not want this at all. Sure, we want our blobs to be random, but only at the point of conception. They shouldn’t change once they exist on the page unless we explicitly tell them to do so.

I found this concept a little tricky to get my head around at first, so I have made a couple of CodePens (best viewed in a browser that natively supports the CSS Paint API) to help demonstrate. In the first example, we have a worklet that sets a random background color, using Math.random():

Warning: resizing the element below will result in a flash of color.

Try resizing the element above and notice how the background color changes as it updates. For some niche applications and fun demos, this might be what you want. In most practical use-cases, though, it isn’t. Aside from being visually jarring, behavior like this could be an accessibility issue for users who are sensitive to motion. Imagine that your worklet contained hundreds of dots that all started flying around and flashing whenever something on the page changed size!

Luckily for us, this issue is quite simple to fix. The solution? A pseudorandom number generator! Pseudorandom number generators (or PRNGs) generate random numbers based on a seed. Given the same seed value, a PRNG always returns the same sequence of random numbers — this is perfect for us, as we can re-initialize the PRNG every time the paint() function runs, ensuring the same sequence of random values!

Here’s a CodePen demonstrating how a PRNG works:

Click “generate” to choose some random numbers — then, click “generate” a few more times. Notice how the sequence of numbers is the same each time you click? Now, try changing the seed value, and repeat this process. The numbers will be different from the previous seed value, but consistent across generations. This is the beauty of a PRNG. Predictable randomness!

Here’s the random-background-color CodePen again, using a PRNG rather than Math.random():

Ah! Much better! The element has a random color set when the page loads, but the background color does not change when it resizes. Perfect! You can test this out by clicking “Rerun” on the CodePen above, and resizing the element.

Adding pseudorandom numbers to our worklet

Let’s go ahead and add a PRNG function above our Blob class definition:

// source: https://github.com/bryc/code/blob/master/jshash/PRNGs.md
function mulberry32(a) {
  return function () {
    a |= 0;
    a = (a + 0x6d2b79f5) | 0;
    var t = Math.imul(a ^ (a >>> 15), 1 | a);
    t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
    return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
  };
}

Now, I’d be lying if I said I understand quite literally anything this function is doing. I discovered this beautiful little snippet of code through Jake Archibald’s excellent article on being predictably random with the CSS Paint API, and have used it in a ton of work since. You can find the original repository for this function over at GitHub — it includes a whole heap of excellent PRNGs and is certainly worth a look.

Note: while I don’t fully understand how this function works, I know how to use it. Often, when working in the generative world (if you are anything like me, anyway!), you will find yourself in this situation. When you do, don’t worry! It is absolutely OK to use a snippet of code to create some art/design without knowing exactly how it works. We can learn by doing, and that’s awesome.

OK, great, we have a PRNG function. Let’s add it to paint():

const random = mulberry32(seed);

In this snippet, we call mulberry32() with our --blob-seed custom property as its seed value, and it returns a brand new function. This new function — random — returns a random number between zero and one.

Lovely, let’s put our shiny new PRNG to use.

A quick aside: Drawing with the CSS Paint API

When working with CSS Paint API worklets, just like HTML <canvas>, we draw everything inside a 2D context. This context has a width and a height. For worklets, the width and height of this context always matches that of the element the worklet is painting to.

Say, for example, we wanted to add a point to the center of a 1920x1080px context, we could visualize it like so:

Points 0,0 in the top-left corner, 960, 40 in the center and 1920, 1040 in the bottom left written in purple. in an otherwise blank white space.

As we begin to write our “render” code, this is good to keep in mind.

How our blob is formed, an overview

Before we write any code, I’d like to show you a little SVG animation of how we will create our blob shape. If you are a visual learner like me, you may find an animated reference helpful for understanding this kind of thing:

To break this process down into three steps:

  1. Plot several equally spaced points around the radius of a circle.
  2. Pull each point a random amount towards the center of the circle.
  3. Draw a smooth curve through each of the points.

Now, things are about to get a tiny bit maths-y but don’t worry. We’ve got this!

Defining the blob’s control points

To start, let’s define the radius of our blob. The blob’s radius determines how large or small it is.

We want our blob shape to always “fit” inside the element it is painted on. To ensure this is the case, we check the width and height of the worklet’s target element and set the blob’s radius accordingly. Our blob is essentially a weird circle, and a circle’s total width/height will always be equal to its radius multiplied by two, so we divide this value to match. Let’s add some code to achieve this in our paint() function:

const radius = Math.min(geometry.width, geometry.height) / 2;

Here’s an image to help explain what is happening here:

Cool! Now that we know what the radius of our blob should be, we can initialize its points:

const points = [];

const center = {
  x: geometry.width / 2,
  y: geometry.height / 2,
};

const angleStep = (Math.PI * 2) / numPoints;

for (let i = 1; i <= numPoints; i++) {
  const angle = i * angleStep;
  const point = {
    x: center.x + Math.cos(angle) * radius,
    y: center.y + Math.sin(angle) * radius,
  };
}

Phew! In this snippet, we “walk” around the circumference of a circle, plopping down some equally spaced points as we go. How does this work?

To start, we define an angleStep variable. The maximum angle between two points on the circumference of a circle is Pi × 2. By dividing Pi × 2 by the number of “points” we would like to create, we have the desired (equally spaced) angle between each point.

Next, we loop over each point. For each of these points, we define an angle variable. This variable is our angleStep multiplied by the point’s index. Given a radius, an angle, and a center point for a circle, we can use Math.cos() and Math.sin() to plot each point.

Note: If you would like to learn a little more about trigonometric functions, I wholeheartedly recommend Michelle Barker’s excellent series!

Now that we have some perfect, beautiful, equally spaced points positioned around the circumference of a circle — we should mess them up. To do so, we can “pull” each one, a random amount, towards the circle’s center.

How can we do this?

First, let’s add a new lerp function (short for linear interpolation) just below where we defined mulberry32:

function lerp(position, target, amt) {
  return {
    x: (position.x += (target.x - position.x) * amt),
    y: (position.y += (target.y - position.y) * amt),
  };
}

This function takes a start-point, an end-point, and an “amount” value between zero and one. The return value of this function is a new point, placed somewhere between the start and end points.

In our worklet, just below where we define the point variable in our for-loop, we can use this lerp function to “pull” the point towards the center position. We store the modified point in our points array:

points.push(lerp(point, center, variance * random()));

For the linear interpolation amount, we use our --blob-variance property multiplied by a random number generated by random() — as random() always returns a value between zero and one, this amount will always be somewhere between zero, and our --blob-variance number.

Note: A higher --blob-variance will result in crazier blobs, as each point can end up closer to the center.

Drawing the curve

So, we have our blob’s points stored in an array. Right now, though, they aren’t used for anything! For the final step in our blob creation process, we will draw a smooth curve through each of them.

To draw this curve, we are going to use something called a Catmull-Rom spline. A Catmull-Rom spline is, in short, a great way of drawing a smooth Bézier curve through any number of { x, y } points. With a spline, we don’t have to worry about any tricky control point calculation. We pass in an array of points, and get a beautiful, organic curve back. No sweat.

Let’s head over to the start of our worklet.js file and add the following import:

import { spline } from "@georgedoescode/generative-utils";

Then install the package like so:

npm i @georgedoescode/generative-utils

This spline function is quite sizeable and a little complex. For this reason, I have packaged it up and added it to my generative-utils repository, a small collection of handy generative art utilities.

Once we have imported spline — we can use it in our worklet’s paint() function like this:

ctx.fillStyle = fill;

ctx.beginPath();
spline(points, smoothness, true, (CMD, data) => {
  if (CMD === "MOVE") {
    ctx.moveTo(...data);
  } else {
    ctx.bezierCurveTo(...data);
  }
});

ctx.fill();

Note: Place this snippet just after your for-loop!

We pass in our points, --blob-smoothness property, and a flag to let spline know it should return a closed shape. In addition, we use our --blob-fill custom property to set the fill color of the blob. Now, if we take a look at our browser window, we should see something like this!

Hooray! We did it! The spline function has successfully drawn a smooth curve through each of our points, thus making a gorgeous (and random) blob shape. If you would like your blob to be a little less rounded, try reducing the --blob-smoothness property.

Now, all we need to do is add a touch more randomness.

A random, random seed value

Right now, our blob’s PRNG seed is a fixed value. We defined this --blob-seed custom property in our CSS earlier, with a value of 123456 — this is great, but it means that the random numbers generated by random() and, therefore, the blob’s core shape, is always the same.

For some instances, this is ideal. You may not want your blobs to be random! You may want to choose some perfect seed values and use them across your site as part of a semi-generative design system. For other cases, though, you may want your blobs to be random — just like the image mask example I showed you earlier.

How can we do this? Randomize the seed!

Now, this isn’t quite as simple as it might seem. Initially, when I was working on this tutorial, I thought, “Hey, I can initialize the seed value in the Blob class’s constructor!” Unfortunately, though, I was wrong.

Since the browser may spin up multiple instances of a worklet to handle calls to paint() — one of several Blob classes may end up rendering the blob! If we initialize our seed value inside the worklet class, this value will be different across instances, and could lead to the visual “glitching” we discussed earlier.

To test this out, add a constructor function to your Blob class with the following code inside:

constructor() {
  console.log(`My seed value is ${Math.random()}`);
}

Now, check out your browser console, and resize the window. In most cases, you get multiple logs with different random values. This behavior is no good for us; we need our seed value to be constant.

To solve this issue, let’s add a little JavaScript on the main thread. I am popping this in the <script> tag we created earlier:

document
  .querySelector(".worklet-canvas")
  .style.setProperty("--blob-seed", Math.random() * 10000);

Excellent! Now when refreshing the browser window, we should see a new blob shape each time.

For our simple demo, this is perfect. In a “real” application, you may want to create a .blob class, target all instances of it on load, and update the seed value of each element. You could also experiment with setting the blob’s variance, number of points, and roundness properties to random values.

For this tutorial, though, that’s it! All we have left to do is make sure our code works OK for users in all browsers, or provide a suitable fallback for when it doesn’t.

Loading a polyfill

By adding a polyfill, our CSS Paint API code will work in all major browsers, with the cost of extra JavaScript weight. Here’s how we can update our CSS.paintWorklet.addModule code to add one to our example:

(async function () {
  if (CSS["paintWorklet"] === undefined) {
    await import("https://unpkg.com/css-paint-polyfill");
  }
  CSS.paintWorklet.addModule("./worklet.bundle.js");
})();

Using this snippet, we only load the polyfill if the current browser does not support the CSS Paint API. Nice!

A CSS-based fallback

If extra JavaScript weight isn’t your vibe, that’s cool. I totally get it. Luckily, using @supports, we can define a lightweight, CSS-only fallback for browsers that do not support the CSS Paint API. Here’s how:

.worklet-canvas {
  background-color: var(--blob-fill);
  border-radius: 49% 51% 70% 30% / 30% 30% 70% 70%;
}

@supports (background: paint(blob)) {
  .worklet-canvas {
    background-color: transparent;
    border-radius: 0;
    background-image: paint(blob);
  }
}

In this snippet, we apply a background-color and a blob-like border-radius (generated by fancy border radius) to the target element. If the CSS Paint API is supported, we remove these values and use our worklet to paint a generative blob shape. Awesome!

The end of the road

Well, folks, we’re all done. To quote the Grateful Dead — what a long, strange trip it’s been!

I know, there’s a lot to take in here. We have covered core generative art concepts, learned all about the CSS Paint API, and made some awesome generative blobs while we were at it. Not bad going at all, I say.

Now that we have learned the basics, though, we are ready to start creating all kinds of generative magic. Keep an eye out for more generative UI design tutorials from me soon, but in the meantime, try and take what we have learned in this tutorial and experiment! I’m sure you have a ton of fantastic ideas.

Until next time, fellow CSS magicians!


The post Conjuring Generative Blobs With The CSS Paint API appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.

19+ Free Google Tools Every WordPress Blogger Should Use

Are you looking for the best free Google tools to grow your WordPress blog?

Google offers a wide variety of free tools to help bloggers and website owners improve their SEO, get more traffic, be more productive, and more.

In this article, we highlight the best free Google tools that every WordPress blogger should use.

19+ Free Google tools every WordPress blogger should use

1. Google Analytics

Google Analytics

Google Analytics is the most comprehensive analytics tool for WordPress blogs and websites.

It tells you how your visitors found your website, what devices they used, what pages they viewed, and how they interacted with your website.

This information helps you better understand your audience, so you can plan and execute an effective content strategy. You’ll be able to see what topics and pages convert the best and steadily improve your website over time.

The easiest way to add Google Analytics to WordPress is using MonsterInsights. It’s the best analytics solution for WordPress used by over 3 million websites.

It lets you view your Google Analytics stats directly in your WordPress dashboard.

MonsterInsights stats dashboard

For more details, see our beginner’s guide on how to install Google Analytics in WordPress.

2. Google Search Console

Google Search Console

Google Search Console is a set of tools that helps website owners monitor and maintain their search engine presence and rankings.

It helps you see what keywords people use to find your site, notify you of site errors holding back your rankings, and much more.

Plus, you can submit an XML sitemap via Google Search Console to help search engines crawl your website better.

The easiest way to add Google Search Console to WordPress is by using the All in One SEO plugin. It’s the best SEO plugin for WordPress used by over 2 million websites.

For more details, see our guide on how to add your WordPress site to Google Search Console.

3. Google Programmable Search

Google Programmable Search

The default WordPress search feature is quite limited and not very good at finding relevant content. As your website grows, you’ll want a way to help your visitors find what they’re looking for.

Google Programmable Search gives you an easy way to add custom search to your WordPress site.

You have complete control over the content it will search, and you can design the search feature to fully blend into your website.

For more advanced search with customization options, we recommend using a WordPress search plugin like SearchWP, but Google Programmable Search can be an affordable option to get started.

4. Google Tag Manager

Google Tag Manager

Google Tag Manager allows you to easily add and manage code snippets, or “tags”, to your website. Tags are commonly used by analytics and marketing tools to add tracking or other features to your site.

Adding tags to your WordPress site usually requires custom code. These custom code snippets load an external script, and it’s hard to manage them all.

Google Tag Manager solves this problem by allowing you to manage all your external codes from one dashboard.

You only need to add one Google Tag Manager snippet to your site, and then you can manage the rest from a single dashboard.

For more details, see our guide on how to install and setup Google Tag Manager in WordPress.

5. PageSpeed Insights

Google PageSpeed Insights

Having a fast loading website is one of the most important parts of providing a good user experience and solid WordPress SEO.

Google PageSpeed Insights is a website performance monitoring tool. It tells you how your website is performing on both desktop and mobile devices.

The results are broken down into different sections, so you can see what’s holding your site back. There are also resources and best practices to help you fix any issues you might be having.

PageSpeed Insights results

For more details on running a website speed test, see our guide on how to properly run a website speed test.

If you’ve found that your website has performance and speed issues, then there’s a lot you can do to improve this.

First, we recommend using high performance WordPress hosting, like Bluehost or SiteGround.

Next, you can use a WordPress caching plugin like WP Rocket. Caching plugins reduce the load on your server and speed up your WordPress site.

If you’re serious about boosting your site speed, then check out our ultimate guide to WordPress performance and speed.

6. Google Mobile-Friendly Test Tool

Google Mobile Friendly Test

For many WordPress websites, a high volume of traffic can come from mobile devices. If your website isn’t optimized for mobile, then you’ll create a poor user experience, and you can lose out on search engine rankings.

The Google Mobile-Friendly Test tool will tell you how well your website is optimized for the mobile web. It will give you a detailed breakdown of any issues and what you can do to fix them.

The easiest way to ensure your website is optimized for the mobile web is by using a responsive WordPress theme. These themes will automatically adjust to your visitor’s screen size, so they’ll look perfect on mobile devices.

7. Google Ads Keyword Planner

Google Ads Keyword Tool

The Google Ads Keyword Planner gives you insights into what people are searching for in Google search. It pulls data from the Google search results and paid advertisers.

Using this tool, you can generate a list of keywords related to your blog and see which keywords get the most searches per month. The data doesn’t provide exact numbers, but it does give general estimates.

Google Ads Keyword Tool results

This tool can also help you generate new ideas for your blog posts, plan your content strategy, and run your own pay per click (PPC) advertising campaigns using Google Ads.

If you’re looking for even more ways to do keyword research, then see our list of the best keyword research tools for SEO.

8. Think with Google Research

Think with Google

Think with Google Research is one of the best market research tools. This collection of tools will help you understand your market, spot new trends, and grow your website or online store.

The data and insights you can gain depending on which tools you use.

For example, the Market Insights tool can help you find new regional or global markets to expand into.

Think with Google market insights

There’s another tool that shows retail categories that are growing in popularity, along with the related search terms. This tells you if the niche you’re in is growing in popularity.

Think with Google rising retail categories

For those who have a YouTube channel, or edit videos, you can use the audience finder tool to uncover new audiences on YouTube.

9. Google My Business

Google My Business

Google My Business is a tool that lets you add your local business information to Google, so it can display your business information in search results.

If you run a local business, or provide services to a local area, then Google My Business is something you cannot miss.

Displaying your business information in Google search results will boost your brand’s search visibility, and bring you new customers and potential leads.

You can combine this with the Local SEO features from AIOSEO to further enhance your local business listings in Google.

10. Google Optimize

Google Optimize

Google Optimize is a tool that helps website owners optimize their websites by running A/B split tests. This lets you compare two different versions of a page to see which converts better.

For example, you can run a split test of two different sales pages to see which one leads to more customers.

By split testing, you can gradually optimize pages on your site to get the highest conversions possible.

You can create a split test simply with the drag and drop builder. Google will automatically show the variations to your visitors randomly and gather data.

For more details, see our guide on how to add Google Optimize to WordPress.

11. Google Adsense

Google AdSense

Google Adsense lets bloggers and website owners easily monetize their websites with display ads. Adsense is one of the longest-running display advertising programs.

Once you’re approved for the program, you can add the display ads to your site and start making money.

To easily manage and display your ads, we recommend using a WordPress ad management plugin.

You can also combine revenue from Google Adsense with other income generating activities like affiliate marketing, and selling online courses.

For more details, see our guide on how to properly add Google AdSense to WordPress.

12. Google Docs, Sheets, Slides, Forms, Calendar, & Gmail

Google Docs, Sheets, Slides, Forms

In terms of productivity tools to help you create better content, Google has you covered. You’ll find a wide range of tools for mobile and desktop, including Google Docs, Sheets, Forms, Calendar, Gmail, and more.

The main advantage of using Google’s productivity apps is the easy sharing features, with full privacy control, unlimited revisions, inline comments, and real time collaboration, all without needing to hit the save button.

Plus, there are all kinds of innovative ways to integrate these tools with WordPress. For example, you can connect WordPress forms to Google Sheets, integrate Google Calendar with WordPress, and more.

There’s also a premium version of these same tools called Google Workspace. This gives you the same functionality, plus a professional business email address, more cloud storage, support for two-factor authentication, and more.

13. Google Drive

Google Drive

Google Drive is a cloud storage tool you can use to store all of your Google Docs, Google Sheets files, and more. The free version shares 15GB of storage across your Drive, Gmail, and Google Photos accounts.

You can use the free cloud storage space to store any file you want and sync them across other devices with a Google account.

If you’re looking for a place to store your WordPress backups safely, then this can be an ideal option.

14. Google Maps

Google Maps

Google Maps gives you a great way to embed interactive maps into your WordPress website. Adding a map to your website can show your visitors where you’re physically located.

This is a must have feature for local businesses like restaurants and cafes.

If you’re a travel blogger, then you can also make use of Google Maps by creating and embedding an interactive map of all the places you’ve been.

15. Google Alerts

Google Alerts

Google Alerts will instantly notify you any time your brand or name is mentioned on the web.

It only takes a few seconds to create a Google Alert for your brand name or keywords, so you’ll get email notifications when you’re mentioned online.

It’s an important tool to use for building a strong brand image. Plus, these alerts can help to notify you of backlink opportunities and potential business partnerships.

16. Google Trends

Google Trends

Google Trends gives you a bird’s eye view of what’s trending in the world of search. You can browse through the latest curated data, or search for keywords related to your niche.

This tool can be helpful in addition to other research tools like the Google Ads Keyword Planner. When you enter a keyword, you’ll be able to see if its popularity is trending up or down.

You can use these insights to decide on new niches to go into or new article topics to write about.

17. Google Fonts

Google Fonts

Typography and font choice play a very important role in the design and usability of your website. Google Fonts is a great place to look for free fonts you can use on your website.

You can download and use these fonts directly from Google, or embed them into your website and serve them from Google’s servers.

For more details, see our guide on how to add custom fonts in WordPress.

18. Google Hangouts

Google Hangouts

Google Hangouts is a free conference call and video meeting tool from Google. It offers secure messaging, phone, and video conferencing for teams and businesses.

This is perfect for smaller teams who want to have quick conversations and easily share Google Docs during the call.

Users can join video meetings with a dial-in number or meeting link.

19. YouTube

YouTube

YouTube is not just a video hosting service, it’s also the second most popular search engine on the web. Millions of users are looking for video content on YouTube all the time.

Adding videos to your blog content can help you get more engagement, but we recommend that you never upload videos to WordPress. Instead, we recommend to host them on YouTube.

We have our own WPBeginner YouTube channel where we host all the videos that we embed on our blog.

If you want to add your YouTube videos to WordPress, then see our guide on how to easily embed videos in WordPress.

Free Bonus Google Tools

There are many more Google tools that are free and can be immensely helpful with your WordPress blog. Some of them are:

Google is often launching new tools and services and many of them are available for free or at a very competitive price.

We hope this article helped you find some new free Google tools that every WordPress bloggers should use. You may also want to see our list of 40 useful tools to manage and grow your WordPress blog and our picks of the best push notification software to get more traffic.

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

The post 19+ Free Google Tools Every WordPress Blogger Should Use appeared first on WPBeginner.

Refined.blog: A Curated List of RSS Feeds for Software Engineering Blogs

In one of the most apropos uses of a .blog domain, Refined.blog is a new website that promotes personal blogging with a curated list of software engineering blogs. It’s a simple site with an index of blogs, their Hacker News scores, tags, and a link to each blog’s RSS feed. The search function is very fast and applies to all columns in the index (with the exception of the feed URL). Columns can be ordered alphabetically, by tag, or by HN points.

“Experience is gold,” Refined.blog creator Musa Ünal wrote in the site’s introduction. “There are many different social media platforms on the internet but we need personal blogs again. It’s hard to find blogs so let’s create this blog list together!”

It’s true – discovering new blogs isn’t easy. If you’re not following the right people on Twitter or don’t happen to be around when a person links to their posts on social media, then you are usually out of luck. Personal blogs are often not very well optimized for search and can get lost in the haystack.

Google Search doesn’t provide a way to narrow results to personal blogs. The Wiby search engine is about the closest you can get for searching these types of websites, although it seems to be limited to older style pages that are based on one subject of interest. Wiby uses Microsoft Bing’s search results combined with Wiby.me results without sending your IP and user agent to Microsoft. Wiby’s about page explains the problem that sites like Refined.blog are aiming solve:

In the early days of the web, pages were made primarily by hobbyists, academics, and computer savvy people about subjects they were personally interested in. Later on, the web became saturated with commercial pages that overcrowded everything else. All the personalized websites are hidden among a pile of commercial pages. Google isn’t great at finding them, its focus is on finding answers to technical questions, and it works well; but finding things you didn’t know you wanted to know, which was the real joy of web surfing, no longer happens. In addition, many pages today are created using bloated scripts that add slick cosmetic features in order to mask the lack of content available on them. Those pages contribute to the blandness of today’s web.

The Wiby search engine is building a web of pages as it was in the earlier days of the internet.

Refined.blog brings more exposure to some of these single-person curated websites. Its creator, Musa Ünal, is considering branching out from an index of software engineering blogs to separate indexes for different topics.

“For example, I am big fan of history bloggers, but it’s very hard to find these kinds of blogs,” he said in response to a question on Hacker News. “If you know such of blogs, please contribute to the project. If we have enough bloggers listed, we can create subdomains like history.refined.blog or art.refined.blog.”

Hacker News comments on the project range from people discovering RSS for the first time and looking for reader recommendations, to people returning to RSS to get their news after becoming jaded by news algorithms and social media platforms. Other commenters shared that they, too, maintain their own lists of curated blogs. Refined.blog used some existing Engineering and Security blog lists as sources for the index.

“I love this,” one person commented on Hacker News. “I’m in the ultrarunning community and I love reading everyone’s blog posts/trip reports/race reports/adventures. But everyone stopped updating them over the past 5 years or so. Now that sort of thing is just an Instagram photo with a paragraph or two. The depth and character of those old blog posts have been lost. I wish in depth blog posts would come back, but in reality, I don’t think they are.”

Another commenter echoes the sentiments of others who have given up on promoting their blogs in the age of social media:

I’ve completely given up on promoting my stuff. It used to be very easy and straightforward. Like minded folks could find new stuff without a problem. Nowadays, there’s just way too much content, the vast majority of very low effort, and you get lost in the noise immediately.

For example, I have an old blog post that got featured in podcasts, on dailyjs, HN, is linked to from MDN, etc. When I wrote it in 2014 I pretty much just submitted it to Reddit, that’s it. Nowadays I couldn’t recreate that exposure — or even a tiny fraction of it — if my life depended on it.

Regardless of whether the site takes off or not, I think it’s important to catalog these attempts to restore the magic of that earlier era where websites offered a real window into people’s knowledge and interests. It may not look the same as many of us remember the old school “vintage” internet, but the blogosphere will continue to evolve as long as bloggers at heart keep experimenting with projects like this. So much of this style of writing has gone to email newsletters, but content that lives publicly on the web has a longer life cycle that can be rejuvenated through linked conversations. Writers can and should be able to embrace both methods of distribution.

Refined.blog is hosted on GitHub and is open to feature suggestions and contributions. One person submitted an issue, suggesting the site add one or more OPML feed links so people can subscribe to all or some of the blogs at once. Ünal said he is working on making an OMPL export for selected blogs.

If you’re looking to beef up your RSS reader with active software engineering blogs, Refined.blog might be a good place to search. There are no blogs referencing WordPress development yet, but the site does have several that focus on tooling, JavaScript, React, PHP, and other technologies that WordPress developers use. The index is specifically designated for personal blogs and company blogs are not permitted. Anyone can submit a blog for inclusion by following the instructions on the main Github project repo or by filling out the Google form with the same information.

TeslaThemes Rebrands, Shifts Focus to Real Estate Market

Earlier this month, TeslaThemes announced that it was rebranding to WPRealEstate. The company wanted to focus its efforts on a single niche in the theming market and cut back on the library of projects it was maintaining.

In 2017, Imagely acquired TeslaThemes. The shop was created in 2013 and had grown its library to 68 themes. Last year, Imagely was acquired, and Nathan Singh was named CEO of the company.

Eric Danzer, the founder and former CEO of Imagely, continued running TeslaThemes and its sister site ShowThemes since the acquisition. He is now ready to turn the page and jump into the next chapter of running a successful WordPress business.

“I’ve decided that, as a business, we’ll do better focusing our energy on a specific niche rather than trying to be all things to all people,” he said.

After several years of running a generic theme shop, the company ran into a brick wall that so many others in the industry I have talked to had hit. It is the realization that maintaining so many disparate projects puts an almost insurmountable burden on the development and support teams.

“TeslaThemes has historically tried hard to serve a lot of small niches,” wrote Danzer in the announcement post. “We’ve had themes for real estate, recipes, musicians, eCommerce stores, photographers, event management, local business listings, and many other use cases. For each of those, we were embedding plugin-level functionality in each separate theme. That created a highly complicated product line that’s difficult to maintain and keep up to date.”

The team had run into the Jack-of-all-trades-master-of-none problem. Tightening the focus would allow the company to focus on and become one of the best in a specific niche. Thus, the shift to real estate.

“As I move on from Imagely, I wanted another big project to focus on,” Danzer added in a personal note. “I wanted it to be something I’m passionate about. I’m passionate about nearly every aspect of real estate. I own multiple rental properties, and I’m working toward a real estate license.”

The company had already been doing well in the real estate market with its previous Realtor theme. It was one of its most popular options.

“On the market side, the real estate market is large enough to sustain a great theme shop,” wrote Danzer. “Yet, it’s also a unique niche — real estate professionals have specific, challenging, hard-to-solve needs.”

Existing TeslaThemes customers will continue receiving support and have access to any products purchased in the past. They will also be able to get the new real estate plugin and theme.

The legacy themes, those created before the 2017 acquisition, are no longer under active development. The company replaced those in November 2020 with the Tesla Pro framework, which Danzer said his team plans to maintain and support for at least another year.

WPRealEstate Plugin and Theme

Screenshot of one of WPRealEstate's theme demos, showcasing its accompanying plugin's custom blocks.
Map, search, and listings blocks in a theme demo.

The team built the plugin on top of the block editor. They also created it alongside the RESO Web API, a modern standard for transporting data in the real estate world.

While there is no public demo of the backend or even any editor screenshots, a peek under the hood reveals several custom blocks. The theme previews showcase map, search, and listings solutions. They also seem to blend the output with the Kadence Blocks plugin.

Instead of launching multiple themes, the company will focus on building a single project with several design options out of the box. Users can import prebuilt content and data as part of the onboarding process.

Danzer said that the new WPRealEstate theme is still a traditional, customizer-based theme. “We’ll start working on a new FSE theme almost immediately though. Between the work needed and waiting for FSE core functionality to mature, I don’t think we’d release that until sometime in 2022.”

As far as I am aware, there are few, if any, robust block-based real estate solutions for WordPress at the moment. Custom post types and metadata serve as the foundation. However, a well-designed layer of blocks on top of that system could make it far easier for agents to build their sites.

GitHub Doubles Down on Developer Community Support

In the past several weeks, GitHub has made two announcements that highlight the company’s dedication to simplified open-source development and governance. These announcements include funding that will support a new GitHub Developer Rights Fellowship and a new Minimum Viable Governance framework. 

Top 6 White Label Branding Plugins For WordPress

The Best White Label Branding Plugins For WordPressUnless you are a web professional who is well-acquainted with the WordPress backend, there is no guarantee you would know that you can customize it as per your requirements. Yes, that is right! This practice is called white-labelling, which is basically the process of removing all mentions of WordPress from your backend and modifying it […]

The post Top 6 White Label Branding Plugins For WordPress appeared first on WPExplorer.

free 3 of 9 barcode

Hello ,
i am using free 3 of 9 barcode to create a bar code of each student in my DB , the problem that in my card it is not shown as it is supposed to be but as 98777

barCode.PNG

so any one knows how i can solve that or what could be the problem???

Thanks

How to Maintain Cybersecurity in the Remote Work Era

While adapting to the current global crisis, businesses had to rapidly transition to a remote workforce to meet customer demands through digital channels. However, this sudden transformation to remote operations presented a whole new challenge of cyber risks. While working remotely, employees may be using home computers to log in to company networks and access confidential information, relying on home internet networks instead of the company's secured network. For remote workers, the importance of cloud infrastructure has increased. They may also be using third-party apps to stay connected with others. And since a work-from-home setup, unlike an office environment, may be slightly more relaxed when it comes to data security, the users are not vigilant enough for cyber risk.

Cybersecurity Risk in a Remote Work Setup

  1. Using unsecured endpoint devices: This makes the system more vulnerable to cyber-attacks.
  2. Personal use of laptops: Employees are using office laptops for personal use like opening personal emails, shopping sites, or any social sites which may put company data at stake.
  3. Lack of physical security: This could take place by leaving the laptop open or leaving the device in an open car. 
  4. Phishing attack: There are more chances of phishing attacks while working remotely as compared to work in an organizational environment.
  5. File sharing: Many companies encrypt their files while storing or transferring in their network but that's not possible for remote employees.

How to Protect Against a Security Threat While Working Remotely

When it comes to protection against security threats while working remotely, there is no one-size-fits-all approach. There are lots of measures organizations need to take to secure their employees. Let’s look more closely at the measures that should be taken to secure remote employees from cyber threats:

Building a RESTful Service Using ASP.NET Core and dotConnect for PostgreSQL

The term REST is an abbreviation for Representational State Transfer. It is a software architectural style created to assist the design and development of the World Wide Web architecture. REST defines a set of constraints that define how a distributed hypermedia system, such as the Web, should be architected. Restful Web Services are HTTP-based, simple, lightweight, fast, scalable, and maintainable services that adhere to the REST architectural style.

The REST architectural style views data and functionality as resources accessed via Uniform Resource Identifiers (URIs). Restful architecture is a client-server paradigm that utilizes a stateless communication protocol, often HTTP, for data exchange between server and client. In REST, the clients and servers interact through a defined and standardized interface.

Getting Started With IaC

Infrastructure as code (IaC) means that you use code to define and manage infrastructure rather than using manual processes. More broadly, and perhaps more importantly, IaC is about bringing software engineering principles and approaches to cloud infrastructure. In this Refcard, explore the fundamentals of IaC and how to get started setting up your environment.

AI Is More Than Robots: Top Applications of Artificial Intelligence in Insurance

The insurance industry is quite prone to uncertainties as it’s highly dependent on global trends, ever-changing rules and regulations, and dynamic demographics of customers. Leading businesses are leveraging artificial intelligence in insurance for redefining the playing field. AI has undergone a massive transformation in the past few years, to the point that insurers can now capitalize on their AI investments with new applications. Let’s have a look at the market size of artificial intelligence in insurance and its prominent use cases in the industry. 

The Global Market

The market size of artificial intelligence in insurance is expected to reach the value of USD 6.92 billion by the year 2028.  It is estimated to grow at a CAGR of 24.05% in the forecast period of 2021 to 2028. 

How to Run SQL Queries With Presto on Google BigQuery

Presto has evolved into a unified SQL engine on top of cloud data lakes for both interactive queries as well as batch workloads with multiple data sources. This tutorial will show you how to run SQL queries with Presto (running with Kubernetes) on Google BigQuery.

Presto’s BigQuery connector allows querying the data stored in BigQuery. This can be used to join data between different systems like BigQuery and Hive. The connector uses the BigQuery Storage API to read the data from the tables.

10 Must-Have VS Code Extensions to Improve Your Productivity

1. Live Server

Live Server allows you to see code changes reflected in the browser. It launches a local development server with a live reload feature both for static and dynamic pages.

Every time you save your code, you'll instantly see the changes reflected in the browser. You'll be much faster at spotting errors and it's much easier to do some quick experiments with your code.

Java Blogs and Podcasts Developers Should Bookmark

If you are a Java developer, engineer, SRE, QA, enthusiast, aficionado, or have any involvement or interest in Java in any capacity, this list is for you.

We scoured the Internet to track down the top Java blogs, Java podcasts, and Java tutorials that you should bookmark. We provide the name, URL, and a brief overview of the resource. In no particular order:

GitHub Explains the Open Graph Images

An explanation of those new GitHub social media images:

[…] our custom Open Graph image service is a little Node.js app that uses the GitHub GraphQL API to collect data, generates some HTML from a template, and pipes it to Puppeteer to “take a screenshot” of that HTML.

Jason Etcovich on The GitHub Blog in “A framework for building Open Graph images”

It’s so satisfying to produce templated images from HTML and CSS. It’s the perfect way to do social media images. If you’re doing it at scale like GitHub, there are a couple of nice tricks in here for speeding it up.

Direct Link to ArticlePermalink


The post GitHub Explains the Open Graph Images appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.