Responsive horizontal scrolling tables for phones in CSS with no additional HTML

For some reason I always forget how to do this, and most tutorials out there suggest wrapping your table in a container <div> tag but as long as you’re using <tbody> (and, ideally, not using <thead> or <tfoot>) then it’s easy with a small bit of CSS and no HTML changes at all.

The trick is to display your <table> as a block, and your <tbody> as a table!

Here’s the code. Fit it into whichever breakpoint makes sense for your site. Mine shown here is the standard phone width breakpoint for WordPress (782 pixels):

@media screen and (max-width: 782px) {

  table {
    display: block;
    overflow-x: auto;
    width: 100%;
  }

  table tbody {
    display: table;
    width: auto;
  }

}

Of course, right after I posted this I found that I had already written about it two years ago with a slightly different solution. Never hurts to have a slightly different perspective.

All the Albums of 2019

It’s been an annual tradition here on Underdog of Perfection: Around the end of November, I post a list of all of the albums I’ve purchased that year, and then a couple weeks later, I rank my top 5.

Well… I skipped it altogether last year, because I hadn’t been paying much attention to new music. The trend has only accelerated this year. It’s partly because I’ve been delving deeply into jazz from the ’60s and ’70s, but it’s more because… man, pop music really sucks these days, and I just haven’t been too interested in the more obscure new stuff either.

And of course, who “buys albums” anymore?

So, here then is my complete list of all the new albums I purchased in 2019. Ones I think are especially good are in bold.

Christopher Willits — Sunset
The Claypool Lennon Delirium — South of Reality
Com Truise — Persuasion System
John Coltrane — Blue World*
JV’s Boogaloo Squad — Going to Market
Lizzo — Cuz I Love You
Mario Alberto Silva — Pan-American Sonata
Steve Hauschildt — Nonlin
The Bad Plus – Activate Infinity
The Bird and the Bee — Interpreting the Masters, Volume 2: A Tribute to Van Halen
TOOL — Fear Inoculum
32nd Street Jazz — self-title**

* Technically a new release!

** OK, I didn’t buy this… I made it, along with my bandmates. But hey, it’s a real release… we even got a ton of airplay on Jazz 88 in August and September! (And yes, it is one of my favorite albums of the year.)

And while I’m at it, here’s my complete (and considerably longer, but still short) list of all the new albums I purchased in 2018, favorites in bold.

Aphex Twin — Collapse EP
The Bad Plus — Never Stop II
Brad Mehldau Trip — Seymour Reads the Constitution!
Christian McBride — Christian McBride’s New Jawn
Courtney Barnett — Tell Me How You Really Feel
The Decemberists — I’ll Be Your Girl
Delvon Lamarr Organ Trio — Live at KEXP!
Elvis Costello & The Impostors — Look Now
Geotic — Traversa
Halloween, Alaska — Le Centre
Helios — Veriditas
Joshua Redman, Ron Miles, Scott Colley & Brian Blade — Still Dreaming
Justin Timberlake — Man of the Woods
Kamasi Washington — Heaven and Earth
King Crimson — Meltdown (Live in Mexico 2017)
Myriad3 — Vera
OMEGA Danzer — FUTURA the Album
Optiganally Yours — O.Y. in Hi-Fi
Steve Hauschildt — Dissolvi
X-Altera — self-title
Yellowjackets — Raising Our Voice
Yes — Fly From Here (Return Trip)

Using The SEO Framework with Advanced Custom Fields

I’m going to go out on a limb and guess that I am not the only WordPress developer who in recent days (in the wake of their obnoxious Black Friday dashboard ad) has switched allegiance from Yoast to another SEO plugin, and that many of those who find themselves in a similar boat (to mix metaphors) have switched to The SEO Framework.

I’ve only been using it for a couple of days, but I already love it. It does all of the things I actually used Yoast for, without any of the other stuff I did not use it for. I mean honestly, maybe readability scores and “cornerstone content” do provide an SEO boost, but I barely understand how to use these tools, so good luck explaining them to my clients in a meaningful way. I suppose they’re more of a tool for full-time SEO consultants who need to pad out their billable hours. (Sorry not sorry. My opinion on the business of SEO hasn’t changed all that much since 2011.)

It wasn’t until the Black Friday ad that I really admitted to myself how much I don’t like Yoast. It does a lot of important things, and does them very well. But it’s obnoxious as hell about it. Pushing features you don’t really want or need into every page of the WordPress admin, and plastering its own over-designed admin screens with tons of garish ads promoting its “premium” features.

Yuck.

The SEO Framework encapsulates all of the key features I liked about Yoast into a single configuration screen, which kindly adheres to the standard WordPress admin UI design language instead of infusing its own brand style into every button and metabox border. It’s refreshingly boring to look at. And it just has the stuff I actually use, like title and description, OpenGraph tags, sitemap XML, the basic elements of SEO that unequivocally matter and can be a pain to build and maintain on your own.

But enough about all of its great features. There’s one key thing it lacks: support for Advanced Custom Fields. My standard “modular design” theme relies almost entirely on ACF’s Flexible Content fields to work its page layout magic, and with all of the page content stored in custom fields instead of post_content, there’s nothing for The SEO Framework to latch onto to auto-generate meta descriptions.

Fortunately, the developer has built in some hooks to allow you to customize the meta description output.

Here’s a barebones starting point:

function my_seo_framework_description($description, $args) {
  if (empty($description)) {
    $description = ''; // Add your own logic here!
  }
  return $description;
}
add_filter('the_seo_framework_custom_field_description', 'my_seo_framework_description', 10, 2);
add_filter('the_seo_framework_generated_description', 'my_seo_framework_description', 10, 2);
add_filter('the_seo_framework_fetched_description_excerpt', 'my_seo_framework_description', 10, 2);

As the developer notes, it’s very important for SEO not to just output the same static description text on every page. You need to have a function of your own that will read your ACF field content and generate something meaningful here.

Fortunately in my case, I had already done that, for generating custom excerpts from ACF content, so I was able to just stick a call to that function into the // Add your own logic here! line. You’ll need to customize your function to suit your specific content structure, but here’s the post that I used as a starting point for my function.

Have fun!

A detailed look at my “Frankenstein” fretless Fender Jazz Bass

I got my first bass — a black Fender Standard (MIM) Jazz Bass — when I was in high school. It wasn’t perfect, but it was a great starter bass. And even though I didn’t really like the black body — I’ve always found black and sunburst to be the most boring and overused guitar finishes — I loved that bass until I could afford to buy a better one, ten years later.

But I always felt like that bass was flawed because of something that was my own fault. I was a curious kid, and one night I decided to take the bass apart. I mean, absolutely as far apart as I could. I removed the strings, the neck, the pickguard, the control plate, the pickups, the bridge… I think I even removed the tuning machines and bridge saddles. And then I put it all back together again.

But I didn’t know what I was doing. I didn’t know that the pickup height should be adjusted for optimal volume balance, so I just cranked them all the way down. I didn’t know that the bridge saddles needed to be adjusted in two dimensions for optimal tuning and playability, so it was out of tune and had terrible action. I didn’t know that the neck tension rod should be adjusted so there was just the slightest concave curve to the neck, so I had fret buzz.

Basically, I just thought it was a mediocre instrument, when in fact I had made it that way.

The lesson I learned was that I should not make any adjustments to my instruments, and it took me decades to get over that.


Fast forward to 2019. I’ve been playing bass in a jazz quartet for a couple of years now, and I’ve been buying new basses! For the past decade I’d owned a really nice Fender Jaguar Bass (MIJ) — red with matching headstock and block inlays — and a kind-of-crappy 5-string MIM Jazz Bass. I decided since I was playing jazz, I needed a fretless, so I went for a minimal expenditure and bought a Squier Vintage Modified Jazz Bass.

I couldn’t believe how good the Squier was for the price! Better than my MIM Fender! So I decided to sell the 5-string. I was hardly playing it anyway. I was curious about short-scale basses, so I bought a MIM Fender Mustang. But I hated it. The quality was crap. I don’t know what’s going on in Fender’s Ensenada factory these days, but I’m not impressed.

For those who don’t know, Squier is Fender’s entry-level sub-brand. Originally a mid-level line made in Japan, then for many years they were very poorly made in China. These days, I’ve since learned, they’re mostly made in Indonesia, using mostly CNC robots (rather than overworked and mistreated human laborers) to keep costs low but consistency and quality much higher than their reputation would lead one to believe.

I also realized short scale was a bad choice if I was simultaneously trying to regain my feel for fretless, so I returned the Mustang and bought… a Squier Vintage Modified 5-string Jazz Bass. It’s also surprisingly great!

Then earlier this year I sold the Jaguar and upgraded to my first ever Precision Bass, an American Professional. It looks just like the bass I learned on that I borrowed from my high school, before I got that first black Jazz Bass. I love it!

But that got me thinking… now that I have a nice solid American Professional instrument, I wanted to tinker a bit with another bass.

As good as the Squier fretless was, I hated two things about it: the synthetic fingerboard material (it just didn’t give enough of a “woody” sound), and the boring sunburst finish. (See above.) By now I’m comfortable adjusting the neck tension, action, tuning, and pickup height, so the idea of doing some customizations (just not to my expensive American Professional!) is not intimidating anymore.

For 2019 Fender introduced a new “Classic Vibe” Squier series, and there I saw the bass of my dreams… a “Daphne blue” Jazz Bass. But it only came in fretted. So I decided this would become the basis for my Frankenstein monster!


Fast forward a few more months, and now the monster is complete. Pretty much the only parts of it that are still the original Squier are the blue body, the tortoise shell pickguard, and the control plate. Everything else is new, with the exception of the tuning machines, which I stole off the Squier fretless (I’ll get to that).

I just love that look of the Daphne blue body paint with the tortoise shell pickguard. That was the inspiration to make all of this happen!

Yes, there’s a bit of headstock vanity, as much as I’m ashamed to admit it… gotta have that Fender logo! But the main reason I wanted this Fender neck, instead of just sticking the Squier fretless neck I already had onto this (which I did, initially), was to get that nice rosewood fingerboard.

Funny thing… when you buy a stock neck from Fender, they really just send you the neck. It just has 4 holes in it for the tuning machines, but you have to supply those yourself. I could have bought a set, but I figured I’d just use the ones from the old Squier fretless neck that I didn’t need anymore. Of course, the screw holes didn’t line up quite right, so I had to drill new ones.

Nuts. The other thing about the stock neck is that the string grooves in the nut aren’t really there… just little pilot notches. You’re supposed to file it down yourself. But a set of nut files is like $80! I considered buying some, but then I learned that this synthetic nut material is soft enough that you can actually “file” it with a set of roundwound strings… so that’s what I did! (I play the fretless with flatwounds.) It’s not totally perfect, but it worked surprisingly well and didn’t cost a thing!

Seriously? Did I really need to swap out the neck mounting plate? Well, yes and no. No, of course I didn’t. But I kind of wanted to, to get rid of any traces of “Squier.” But there was actually a good, practical reason for this. I wasn’t 100% sure the screw holes for mounting the neck would line up properly between a Squier body and a Fender neck. I was pretty sure they would. But not positive. This was an inexpensive (about $15) way to confirm that it would work, before spending a couple hundred bucks on a neck. It worked!

A Fender hi-mass bridge. The stock Squier bridge was perfectly fine, but I didn’t care much for the changes they made to the bridge saddles with the Classic Vibe series. Initially I swapped in the saddles from the Vintage Modified fretless, but a hi-mass bridge is not a huge investment and it does improve sustain… plus it just looks better.

DiMarzio noiseless pickups. Without a doubt this was the best upgrade across the board. The stock pickups just had kind of a weak and undefined sound… it was impossible to get that classic Jazz Bass “twang” from the bridge pickup. Plus you could never really solo one pickup because the 60 Hz hum was awful! These pickups are a lot hotter than the stock ones and give a very distinctive tone. But most importantly, they’re wired as split coils so there’s absolutely zero hum with one pickup soloed!

Of course, there’s always something. These pickups are taller than the stock ones, and they couldn’t be seated low enough to have the proper distance from the strings. I needed to rout out the body cavities deeper for them. But I don’t own a router, or a drill press, or anything that you should probably have to do this job right. But I was determined to handle this the way I’ve handled everything else on this project: fast, cheap and out of control. I found the most suitable bit I had on hand for my hand drill, and set to work removing wood. The end result was pretty ugly (and honestly, still not quite deep enough), but it’s hidden, and now things look and sound great!

Why live shipping calculations for ecommerce are the bane of my existence

I’ll be frank: I don’t really like ecommerce. I’ve floated for most of my 23-year career in web development in the fantasy of a Platonic ideal of an online world: bytes streaming from point to point on a perfect network. No messy complexities of the physical world to concern me.

Well, obviously none of that is true. And I’ve been dealing with ecommerce in some form or another for at least 20 of those 23 years. But I still find the nitpicky details of sales tax and shipping logistics both mind-numbingly dull and infuriatingly (seemingly pointlessly) complex.

Which brings me to the crux of today’s rant. Bringing simplicity to all of this… or, at least, to the part I have to deal with.

Granted, I am not an accountant, and I don’t have to deal with balancing my clients’ numbers at the end of the quarter. But from my perspective, there are some simple solutions to the fact that calculating shipping sucks.

These days I deal mainly with WordPress, and therefore with WooCommerce. There are a lot of extensions to WooCommerce now for live shipping rate calculations. You can pay an annual fee for tools that connect you to shippers’ APIs to give you exact shipping rates. And all you need to do is:

a) determine exact weights and dimensions of all of your products,

b) figure out exactly what types of boxes/packages you’re going to use (and determine their exact weights and dimensions), and

c) plug all of those numbers into WooCommerce, and also

d) decide which of those types of packages are applicable to which products, create the appropriate Shipping Classes, and apply them to the corresponding products; then

e) set up Shipping Zones for each part of the world you’ll ship to,

f) add shipping methods in each of those zones for each of the shippers you’re working with,

g) go into each shipper, in each Shipping Zone, and select from the dozens of shipping services each shipper offers (although you might have to do this multiple times, if you want to restrict the methods you offer based on your Shipping Classes), then

h) test adding these products to your cart, enter an applicable shipping address, and see if you get the right shipping charges… or any shipping charges at all… because you very likely won’t, because for instance you may not realize that

i) WooCommerce Services no longer offers free access to USPS live shipping calculations for new sites created after WooCommerce 3.6, and you now need to buy a separate extension for $79/year to do that. But the free plugin won’t give you any indication that this is the case; it will still show you all of the shipping methods in the configuration pages, it just won’t give you back any rates on the checkout page, and you won’t have a clue as to why until you stumble upon a small note to this effect on the WooCommerce documentation website.

In case you didn’t guess, I just went through all of this today. And this was on a site that only has 7 SKUs!

Of course, there’s a different way to approach this. You could, instead:

a) offer flat-rate shipping.

Obviously it’s not quite that simple. But here’s the thing: there’s no law saying you can’t charge customers more for shipping than it costs you. That’s the whole idea behind “shipping and handling.” In fact, whether you’re doing the fulfillment yourself, or you’ve hired an outside fulfillment vendor, you’re paying more to ship those products than the shipper’s calculated rate anyway, so you should charge more.

Here’s what I recommend.

First, decide on a shipping method. Or maybe a few. Depending on what you sell, you might want to use USPS Media Mail (if it’s applicable). Otherwise, you’ll most likely want to offer two shipping methods: a) ground (cheap but slow) and b) 2-day air (more expensive but reasonably fast). You choose the vendor you like best: USPS, UPS, FedEx, some guy they call “Crusty Pete” with a rusty old pickup truck, etc.

Find out approximately what it will cost, on average, to ship each of your products, by each of these methods. (This is a good use for Shipping Classes.) Then tack on an arbitrary “handling” fee, say $1 per item for ground and $2 per item for 2-day air.

Now, decide: do you want customers to see a shipping charge, or do you want to offer “free” shipping? My logic for this is relatively easy. You just need to balance these two considerations:

  1. People like to see free shipping.

  2. People don’t like to see ridiculously high prices for individual items.

If you are going to offer “free” shipping, you’re really going to take that approximated shipping cost for each item and add it to the selling price of the item itself. Does that make the price of the item seem exorbitant? If not, go for it. People like free shipping.

As long as the shipping price itself isn’t so huge that it causes people to balk when they see it on the checkout page, you can keep the item prices low and present the shipping charge there. Or, a mix: offer “free” ground shipping, included in the price of the item, and then at checkout give the option of “free ground shipping” or paid 2-day air, with the 2-day air prices set at whatever you determined they should be, minus the amount you had already rolled into the item prices for free ground shipping.

Flat-rate shipping isn’t literally flat rate, as in one fixed price no matter what you’re buying. Generally it’s a formula… a base price, plus a multiplier based on the number of items.

For instance, your flat-rate formula might be $5 base plus $2 per item. The customer buys one item? $7 shipping. Two items? $9 shipping. You just plug the formula into the settings, and the rest gets calculated automatically.

The whole purpose of having shipping charges at all is to cover your expenses. Paying an annual license fee for a live shipping calculator extension, plus paying a developer or consultant for their time in helping you wade through all of these complicated configurations, and troubleshoot the problems that crop up, only to end up charging customers exactly what you’re paying for shipping and not a penny more just ends up costing you money. And the fact that these extensions include an option to add on an arbitrary amount above the calculated rate gives the game away… You don’t have to charge customers exactly what you’re paying for shipping. You just need to cover your expenses.

Your time and (my) mental wellbeing are expenses too. As long as your accountant doesn’t get too frustrated with the variable amount of ancillary income you’re getting from the modest overage you’ve calculated into shipping and handling charges, free or flat-rate shipping is a much simpler and more manageable alternative to live shipping calculations.