Slanted Background Stripes

Why Eat Your Coffee? page

Sample effect

While working on a recent project, I needed to use angled background stripes on a number of pages.

Here are a couple of requirements that limited my options:

  • Angled stripes with text content and a background color and/or image
  • Angled stripes stacked on top of each other

CSS transform: skewY()

My first idea was to try transform: skewY(4deg) on a wrapper element and transform: skewY(-4deg) on the internal element(s). Makes sense, right? Skew it and then unskew it? Two problems with this approach though:

  • Causes extra work for the rendering engine (and therefore performance hit)
  • Messes with layout: if you have multiple elements with the negative skew, the tops get offset the further down the row you go because the wrapper itself is skewed.

CSS pseudo-content with transform: skewY()

My next idea was to simply use :before and :after pseudo-content blocks and use transform: skewY(4deg) to angle them as required.


  • Cross-browser
  • Fairly easy to implement: specify an angle and you’re done


  • Only works with background images/colors
  • Can’t stretch <img…/> tags to cut them off at an angle

Sample Code

CSS clip-path: polygon() property

The next idea and the one I ended up using for most of the project was the clip-path: polygon() property along with vw units to keep the angle consistent at all browser widths.


  • Work with <img…/> tags and other content (lets you clip off parts of an image)
  • Much less code 😄


  • Doesn’t work in any version of IE
  • A bit more complicated to figure out since you have to ensure child elements have enough padding so they don’t end up getting clipped

Sample Code

WooCommerce Downloadable Products: Granting Permissions to Previous Customers

If you’re using WooCommerce to provide downloadable products and add new a new download, previous customers do not automatically get access to it as of v3.x.

Here are a couple of options:

Use a Plugin to force Legacy Behavior

Here is one plugin that reverts the behavior to v2.6.x, but is not recommended due to heavy database usage.

Use MySQL Queries to Grant Access to Previous Customers

Another method to grant access for previous customers to new downloadable items is to run a set of database queries to update their permissions.

This is a one-time process and can handle multiple new files, as well as limit the access to orders after a specific ID number or date.

Here are the steps, tested on WooCommerce v3.2.6:

  1. If you haven’t already, add the new downloadable file(s) to your WooCommerce product(s).
  2. Log in to your MySQL server using a MySQL client (Sequel Pro and phpMyAdmin are two good options) and backup your entire database.
  3. Create a temporary table to hold data; run this SQL query to get it set up. Run this query only once and don’t close your MySQL client when it’s finished.
  4. Get the download_id hash.
    1. In the wp_woocommerce_downloadable_product_permissions table, find a previous order (compare the order_id column against order IDs in your WordPress WooCommerce admin area) and note the download_id value(s) for previous customers.
    2. Place a test order and note the order ID number.
    3. In the wp_woocommerce_downloadable_product_permissions table, find your test order ID in the order_id column and make note of the new download_id value(s) as compared with step A above.
  5. Add all previous customers to the temporary table.
    • Make sure to substitute your WordPress installation’s database prefix in place of the wp_ and set the variables at the top accordingly, then run all these queries. The final query is a sanity check and will show you everything in the temporary table.
    • If you have multiple products/variations/downloads to add, edit the variables as necessary and run all the queries again for each combination to add another batch of customers to the temporary table.
    • Do not close your MySQL client or the temporary table will be dropped along with whatever content is in it. (If you made a mistake and need to empty the table, you can run TRUNCATE temp_wp_woocommerce_downloadable_product_permissions and then re-run these queries as necessary.)
    • When you have added all the product/variation/download combinations to the temporary table, run this query to update the download permissions table for those customers.
    • Double-check that everything on your site is working as it was previously; I recommend taking another backup of your database to be safe. If something happens, you can compare the two backups to see what is different.
    • Close your MySQL client and the temporary table will be dropped by the server.

Now users who have previously purchased a downloadable product will see newly-added downloadable files in their account.


How to Use Backblaze B2 with Sermon Manager for WordPress

If you’re hosting a church website on shared webhosting, chances are they limit how much space and bandwidth you can use each month. Uploading sermons each week can eat into those limits very quickly.

Enter Backblaze B2, a cloud storage option costs less than a quarter of what Amazon S3 would cost for the same amount of storage. Backblaze has been around for years as a computer backup solution and has made their name by providing reliable storage at low cost.

In fact, the first 10GB of storage is free, so you might even be able to host your sermons at no cost at all.

Getting Started with Backblaze B2

  1. Sign up for a Backblaze B2 account; you don’t even need a credit card to get started.
  2. Once you’re in your account, click on Buckets and then on Create a Bucket.
    Backblaze B2 buckets
  3. Enter a unique name for the bucket, set the privacy settings to Public, and click Create a Bucket.
    Creating a B2 bucket
  4. Click on Show Account and Application Key; make a note of your Account ID and then create an application key. You’ll need these later.

Setting Up Cyberduck

Backblaze B2 provides the ability to upload files right in the web browser, but it also provides support for a growing list of third-party tools, including the popular Cyberduck FTP client.

I recommend the Cyberduck client because it’s easy to use and feels familiar: it lets you work with files just like you normally do on your desktop.

Here’s where to get it:

Here’s how to get started:

  1. Open Cyberduck
  2. Go to the Bookmarks menu and choose New Bookmark
  3. Choose Backblaze B2 from the dropdown menu at the top of the window
    Creating a Cyberduck bookmark
  4. Set a name if you want; add the Backblaze B2 Account ID and close the window

You’ll only need to go through this process once.

Adding Sermons

Now that all the setup is out of the way, adding sermons is pretty easy. Here’s how:

  1. Open Cyberduck
  2. If it doesn’t open automatically, double-click the B2 server in your list of connections
  3. Open the bucket you just created
  4. Drag your sermon audio (or video) file into the Cyberduck window and wait for it to finish uploading
  5. Right-click on the sermon, go to Copy URL, and choose HTTPS URL
    Copying a B2 HTTPS URL
  6. Paste that URL into the the Location of MP3 field in Sermon Manager

Advanced Options

For more advanced users, you can set up CloudFlare and Backblaze B2 to work together and potentially save more money; here’s an article explaining how to set up a “vanity URL” and use CloudFlare’s caching.

If you set up a vanity URL as described in that article, you’ll still want to copy the HTTPS URL from Cyberduck, but when you paste it into Sermon Manager, modify it to include your vanity URL instead of Backblaze’s domain name.


Backblaze B2 is a great cost-effective option for hosting sermon media, and is easy to use with the popular Sermon Manager for WordPress plugin.

WPForms: Force Async Scripts

This little plugin has one job: make the Google Recaptcha script loaded by WPForms load asynchronously.

Get the plugin on GitHub.

Installation Instructions

  1. Copy the wpforms-recaptcha-async.php file to your wp-content/plugins/ directory (or compress to a zip file and upload in the WordPress backend “Plugins > Add New”
  2. Activate
  3. That’s it. All the merged scripts will be loaded with the async and defer attributes.

Merge + Minify + Refresh: Force Async Scripts

This little plugin has one job: make all merged scripts produced by the Merge + Minify + Refresh plugin load asynchronously.

Get the plugin on GitHub.

Installation Instructions

  1. Copy the merge-minify-refresh-async.php file to your wp-content/plugins/ directory (or compress to a zip file and upload in the WordPress backend “Plugins > Add New”
  2. Activate
  3. That’s it. All the merged scripts will be loaded with the async attribute.

Listing Unique Font Stacks on a Webpage

I just put together a new tool to list all the unique font stacks on a web page, intended to help with diagnose and remove unnecessary webfonts and save page load time.


Download this file and include in your page source, or copy-and-paste it into your browser’s JS console, then run the styleInPage() function with the CSS style you want to inspect as the parameter.


// Show all unique font stacks in use on the current page

// Show a list of all DOM elements with their computed font stack
console.log(styleInPage('fontFamily', true));

// Highlight all DOM elements using font stack 8
var fontStacksInUse = styleInPage('fontFamily');

php iconA quick-and-dirty PHP script to unserialize a string in PHP.

Clone (or download and expand the zip file) into your documents root and point to the folder.

Enter your serialized data into the `textarea`, submit, and boom!—your serialized data is expanded to a much more human-readable view! screenshot

Created for use with this Alfred custom search (note that if your serialized string is longer than 4,000 characters, it may cause a 414 “Request Too Long” error).