Spoticalc – Spotify bandwidth calculator

Recently, we were wondering with a couple of friends how much data Spotify was sucking out of our cell phone data plans.

I knew that with a 3GB/mo. plan I could get away with most of my needs, but there was also streaming quality into the mix.

Spoticalc - Spotify bandwidth calculator
Spoticalc v2
Continue reading →

Everything I know about CSS Variables Custom Properties

Brain dump about CSS Custom Properties, AKA CSS Variables

They are not variables

They are actually called CSS custom properties. Huh.
We’ll refer to them as variables for brevity.

Declaring variables

To declare new variables, you just add a new property that begins with --, inside a ruleset:

:root {
  --color-main: #76fadd;
  --color-text: #282828;

What is :root?

If you notice, in the previous example, in the previous MDN link and other tutorials, you’ll see that variables are declared inside a :root, instead of html {...}, body{...} or whatever.

According to MDN, :root is a pseudo-class that matches the root of the tree representing the document. In this case, it’s identical to the html selector, except that its specificity is higher.

So why not use html then? Well, it’s perfectly fine.
CSS-Tricks explains this very clearly:

In an HTML document the html element will always be the highest-level parent, so the behaviour of :root is predictable. However, since CSS is a styling language that can be used with other document formats, such as SVG and XML, the :root pseudo-class can refer to different elements in those cases. Regardless of the markup language, :root will always select the document’s top-most element in the document tree.

Using variables

.element {
  color: white;
  background: var(--color-main);


CSS Variables are inherited exactly like normal CSS properties. They are, after all, CSS properties and not variables. In the following Pen you can see how children-1 can override --color-bg declaration defined in it’s parent (.child), but parent can’t, since it has no access to it. --color-bg declaration is “below” parent it so it can’t cascade down to it.
Inheritance demo CodePen


The first line of defense against undefined values is CSS’s cascading properties:

:root {
  --color-main: #76fadd;
  --color-text: #282828;

.element {
  background-color: #333333;
  background-color: var(--color-main); /* only interpreted by supported browsers*/

If the current browser doesn’t support CSS custom properties, it will ignore line 8 and apply a #333333 background. This is a very simple and isolated example, but it can be useful when some of these variables are generated and injected programmatically.

More importantly, fallback values work for browsers that do support custom properties. Fallback values are used when the given variable is not yet defined. The syntax is var(--variableName, defaultValue):

.element {
  background-color: var(--color-main, #333333);

If --color-main was not yet initialized or is by some reason invalid (maybe because it’s generated by user input), the background color of the element will be #333333.

Dark mode

One of the perfect use cases for CSS variables is obviously making a dark mode UI. Here’s a quick Pen on how to achieve that very quickly:

Congrats, now you have to maintain and test two versions of every element in your site.

Dark Mode CSS queries

In 2019 browsers started introducing the prefers-color-scheme media query, in order to write CSS depending on the users’s OS setting. That means we can show a dark UI or tweak some styles for users that have a dark theme setting enabled on their OS:

:root {
  --color-bg: #fff;
  --color-text: #333;

@media (prefers-color-scheme: dark) {
  :root {
    --color-bg: #333;
    --color-text: #fff;

Browser support

Support is pretty good overall:

  • Edge 16 (Oct 2017)
  • Firefox 31 (Jul 2014)
  • Chrome 49 (Mar 2016)
  • Safari 9.1 (Mar 2016)
  • Opera 36 (Mar 2016)

Work in progress

I’ll be updating this page soon. If this helped you clear up some thoughts or something seems off, let me know!

Useful links

How to convert JPGs to WebP automatically

The easiest way to convert a ton of JPGs to WebP is to use the cwebp command line utility written by the WebP team. Here’s how I do it using a very simple Bash script:

for f in `find ./source/uploads -name *.jpg` ; do
	dir=$(dirname "$f")
    filename=$(basename -- "$f")
    cwebp -q 90 $f -o $dir/$filename.webp;

This goes through all JPG files in ./source/uploads folder, converts them with a 90% quality rate and writes the output to the same origin.

How to convert SVG files to PNG automatically

A few weeks after the designer handed off about 500 tidy little icons, some customer requested PNG versions for all those.

Of course one option would be to export all again in PNG format. While possible, I wanted to simplify the designer’s job after creating new icons: hand off the SVGs and we’ll take care of the rest. After researching some alternatives, I ended up implementing this in Bash, using rsvg-convert from librsvg.

Install librsvg in macOS

brew install librsvg

The following script goes through all .svg files in a particular /files folder and converts them to a 400 width PNG file, if a PNG file does not already exist:

# File:

for f in ./files/*.svg; do
  filename=$(basename -- "$f")

  if test -f "./files/$filename.png"; then
    echo "$filename already exists. Skipping."
    echo "Converting" `basename $f`
    rsvg-convert $f -o ./files/$filename.png -w 400


Make sure you have permissions to execute the file:

chmod +x

And run it:


Useful links

Enable Custom Post Order via code in WordPress

Recently I enabled the great Simple Custom Post Order (SCPO) plugin in a bunch of sites. After you activate it you can go into its settings and enable sorting for all posts, custom post types, taxonomies, etc.

We had a particular case though. At my current job, we manage a network of nearly 200 WordPress sites. It makes no sense logging to 200 sites’ admin to update their values. In every site, we needed to

  1. Upload and activate SCPO.
  2. Enable sorting for categories only.

First one can be handled by ManageWP or other remote-access tools. The second seemed a bit more tricky. There’s not much documentation, since the plugin works great out of the box.

I asked this question in the forum and after that and a bit of digging into the code and database, I found a solution:

SCPO options are stored in wp_options table, under scporder_options name. In other words, you can manipulate it using the update_option filter. Or, as @mplusb mentioned:

The option’s name where they are stored is: scporder_options
which is an array and in ‘objects’ will keep all the custom posts and in ‘tags’ the taxonomies.

Answer from @mplusb

That means a simple solution is:

update_option('scporder_options', array('objects' => '', 'tags' => array('category')));

I also added a check to ensure the plugin is active and a second one to make sure we are not overwriting options if scporder_options is set, so the final code is:

if (is_plugin_active('simple-custom-post-order/simple-custom-post-order.php')) {
    if (!get_option('scporder_options')) {
        update_option('scporder_options', array('objects' => '', 'tags' => array('category')));

How to remove captions from Instagram embeds in WordPress

This is a simple code snippet to achieve just that in Instagram embeds, via shortcode or using Gutenberg.

function custom_instagram_settings($code){
    if(strpos($code, '') !== false || strpos($code, '') !== false){ // if instagram embed
	    $return = preg_replace("@data-instgrm-captioned@", "", $code); // remove caption class
	    return $return;
    return $code;

add_filter('embed_handler_html', 'custom_instagram_settings');
add_filter('embed_oembed_html', 'custom_instagram_settings');

[instagram url= hidecaption=true]

You can achieve the same effect in single embeds by using the following shortcode

[[instagram url= hidecaption=true]]

Here’s the result

[instagram url= hidecaption=true]


Use this snippet if you want to achieve a similar result wit YouTube embeds:

/* Youtube Videos remove show info related etc */
function custom_youtube_settings($code){
    if(strpos($code, '') !== false || strpos($code, '') !== false){
	    $return = preg_replace("@src=(['\"])?([^'\">\s]*)@", "src=$1$2&cc_lang_pref=en&hl=en&showinfo=0&rel=0&autohide=1&modestbranding=1&iv_load_policy=3", $code);
	    return $return;
    return $code;

add_filter('embed_handler_html', 'custom_youtube_settings');
add_filter('embed_oembed_html', 'custom_youtube_settings');

Has this worked for you?

Found: on Reddit

Photo by Hans-Peter Gauster on Unsplash

Getting started with Jigsaw

There are tons of static site generators. However, Jigsaw has been catching some wind. So, what stands out with it?

  • Blade templating system “just like your Laravel apps.”
  • Laravel Mix, Browsersync integration. 
  • Familiarity with Laravel ecosystem.
Continue reading →

Don’t design your emails

I just came across a post from 2016, about why you shouldn’t design your email campaigns. This probably doesn’t apply to all situations and industries, but I know for a fact that many clients pay for lots of hours of crafting, debugging and testing custom templates that aren’t really worth the time.

Link: Don’t Design Your Emails