Category: Code

  • Taxonomy Queries with WordPress v2 REST API

    In order to access posts by a taxonomy query via the v2 WP REST API, you’ll need to do a little set-up first. Let’s say we’re starting a beer blog, and we’re attaching two custom taxonomies to our posts: “styles” and “breweries”.

    Creating the Taxonomies

    When you register the taxonomy using register_taxonomy, you have to make sure you set it to be available via the API. To do this, make sure you have 'show_in_rest' => true to make it accessible in the API and provide thename you want to access it with in the URL with 'rest_base' => 'beers'. Here’s sample code for registering our taxonomies called “styles” and “breweries” that’s accessible via the API:

    
    register_taxonomy(
        'styles',
        [ 'posts' ],
        [
            'labels' => [
                'name'              => 'Styles',
                'singular_name'     => 'Style',
            ],
            'show_in_rest' => true,
            'rest_base' => 'styles'
        ]
    );
    
    register_taxonomy(
        'breweries',
        [ 'posts' ],
        [
            'labels' => [
                'name'              => 'Breweries',
                'singular_name'     => 'Brewery',
            ],
            'show_in_rest' => true,
            'rest_base' => 'breweries'
        ]
    );
    
    

    Now you can find all terms in the Breweries taxonomy with /wp-json/wp/v2/breweries and all the Styles with /wp-json/wp/v2/styles

    WP REST API Taxonomy Query

    In order to get posts attached to a specific beer style in the styles taxonomy, you can query it by style term ID in the URL by appending ?style=[term_id].

    For example, let’s say IPAs have a term_id of 25. To find all posts with the term IPA, you can do: /wp-json/wp/v2/posts/?styles=25

    For multiple terms, add more comma separated IDs, like: /wp-json/wp/v2/posts/?styles=25,26,27

    This is equivalent to the WP_Query:

    
    $args = [
        'post_type' => 'post',
        'tax_query' => [
            'relation' => 'AND',
            [
                'taxonomy'         => 'styles',
                'field'            => 'term_id',
                'terms'            => [25,26,27],
                'include_children' => false
            ]
        ]
    ];
    $query = new WP_Query($args);
    
    

    Note, this will not find all posts that include ALL of the styles (25, 26, and 27) but find posts that have at least one of the terms (25, 26, or 27).

    Multiple Taxonomy Queries

    If we want to find posts by both beer style and brewery, we simply add more parameters to the URL. If we want all posts with the term IPAs (term_id 25) from Boulevard Brewery (term_id 33), we’d do: /wp-json/wp/v2/posts/?styles=25&breweries=33

    This is the WP_Query equivalent of:

    
    $args = [
        'post_type' => 'post',
        'tax_query' => [
            'relation' => 'AND',
            [
                'taxonomy'         => 'styles',
                'field'            => 'term_id',
                'terms'            => [25],
                'include_children' => false
            ],
            [
                'taxonomy'         => 'breweries',
                'field'            => 'term_id',
                'terms'            => [33],
                'include_children' => false
            ]
        ]
    ];
    $query = new WP_Query($args);
    
    

    Complexity Tradeoff for Simple URLs

    Because the structure is so simple, ?[rest_base]=[comma_separated_term_ids], it doesn’t allow you to have all the power of WP_Query(). From looking at the WP core code, it looks like the following are NOT supported out of the box:

    • Relationship "OR" queries
    • Querying by slug instead of term_id
    • Setting include_children to true.
    • Using the operator argument to set if you want it to find posts that are in all the terms you passed (using operator=>'AND') or finding posts that are NOT IN the term(s) you passed.

    As of this writing in WordPress v4.9.4, to do any of those more complicated queries, you’d have to add custom filters to the API to make them accessible.

  • Tutorial: How to Minify & Version a JS File with NPM Scripts

    One of the studies with the Center for Media Engagement needed a straightforward way to maintain and deploy a single JS file. I didn’t want to use a big fancy WebPack or Gulp setup when all we needed was to minify and version a single JS file, so I turned to using npm scripts.

    tl;dr

    The following package.json file, when you do npm run production will:

    1. Check your package.json version and increase it by 0.0.1
    2. Minify your script.js file as script.min.js
    3. Add the new version number and build time to the header of your script.min.js file
    {
      "name": "my-rad-scriptz",
      "version": "0.0.1",
      "description": "This script is the kewlest!",
      "scripts": {
        "minifyJS": "uglifyjs scripts.js --compress --mangle --warn --output scripts.min.js",
        "production": "npm run version:bump --silent && rm -f scripts.min.js && npm run minifyJS --silent && npm run version:add --silent",
        "version:add": "echo "/*! My Rad Scriptz!!!!1!11! v - $(npm run version:extract --silent)n * © Someone probably n * Build time: $(date '+%m-%d-%Y %H:%M:%S')n */n$(cat scripts.min.js)" > scripts.min.js",
        "version:bump": "npm version patch --no-git-tag-version --silent",
        "version:extract": "cat package.json | grep version | head -1 | awk -F: '{ print $2 }' | sed 's/[",]//g' | tr -d '[[:space:]]'"
      },
      "author": "Rad D00d",
      "devDependencies": {},
      "dependencies": {
        "uglify-js": "^3.3.11"
      }
    }
    

    Thanks to the A11y Dialog project, as that’s where I got the command for reading the version number from package.json.

    The Set-up

    To get started, create a new directory and script file to host your project. I’ll use terminal commands to do this stuff because it’s useful to know and we’ll need to be in terminal when we start running npm commands anyways.

    # create the directory
    mkdir my-rad-project
    
    # change directory (cd) into your new project directory
    cd my-rad-project
    
    # create a scripts file
    touch scripts.js
    
    # create a package.json file
    touch package.json
    

    Copy and paste the package.json contents above into your package.json file.

    Now, make sure you’re in your my-rad-project directory (you didn’t change it, did you!?!?) and run in terminal:

    npm install
    

    This will install any packages in the devDependencies and dependencies sections of your package.json file. In this case, it’s only uglify-js, which is what we’re using to minify our JavaScript file.

    Now, when you build production assets it will take whatever is in your scripts.js, minify it into scripts.min.js and add the new version number into the header of scripts.min.js.

    While still in your my-rad-project directory to kick off the minification process, run in terminal:

    npm run production
    

    How it Works

    Our package.json file contains a scripts object where we can define shortcuts for running terminal commands. Each of those scripts we could run via terminal, but why would we when can just do npm run production?

    When we do npm run production, it runs whatever is in the production section of the scripts. In our case, it’s this:

    "production": "npm run version:bump --silent && rm -f scripts.min.js && npm run minifyJS --silent && npm run version:add --silent"
    

    This one command, npm run production, ends up running multiple other commands, chaining them together with &&.

    # npm run production runs... (the --silent tag suppresses output to terminal. otherwise you get lots of unnecessary stuff output in your terminal window)
    npm run version:bump --silent && rm -f scripts.min.js && npm run minifyJS --silent && npm run version:add --silent
    
    # which runs npm run version:bump (increase the version of package.json by 0.0.1)
    npm version patch --no-git-tag-version --silent
    
    # and then runs rm -f scripts.min.js to delete our old scripts.min.js file
    
    # and then runs npm run minifyJS to minify the script.js file into script.min.js
    uglifyjs scripts.js --compress --mangle --warn --output scripts.min.js 
    
    # and then runs npm run version:add to prepend a comment to scripts.min.js with the new version number and timestamp
    echo "/*! My Rad Scriptz!!!!1!11! v - $(npm run version:extract --silent)n * © Someone probably n * Build time: $(date '+%m-%d-%Y %H:%M:%S')n */n$(cat scripts.min.js)" > scripts.min.js
    
    # which, during npm run version:add has $(npm run version:extract) that runs to find the new version number
    cat package.json | grep version | head -1 | awk -F: '{ print $2 }' | sed 's/[",]//g' | tr -d '[[:space:]]'
    

    Whew! See why it’s lots easier to just do npm run production?

  • WordPress Actions Made Simple

    I was coding WordPress themes for an embarrassingly long time before I fully understood how to use WordPress actions. This is how I wish someone had explained them to me when I was beginning as a developer.

    I’m going to walk through this abstractly, not with actual WordPress hooks. The point of this article is to understand what WordPress actions are, why they’re useful, and how to use them.

    The WordPress Actions of my Dog

    My dog, Sycamore, has a good life. Napping, playing, eating: what’s not to like? Let’s build a schedule of an ordinary day in the life of Sycamore with WordPress actions.

    The set-up of the actions will be one action for each hour of the day: 1 – 24. When a page loads, it will run all of the 24 actions one immediately after another.

    You generally will not add any do_action() to your theme. This is just for demonstration. The important thing to know here is that every time a page loads, it will run 24 actions: one for each hour of the day. So, go to the page, and it will, run, in order:

    do_action('1_oclock');
    do_action('2_oclock');
    do_action('3_oclock');
    // etc, until...
    do_action('24_oclock');
    

    Each time one of those actions runs, it looks for anything else hooked into the action with the same name (like, ‘1_oclock’) and then runs that action at that time.

    The Schedule

    Now that we have our actions for each hour of the day running, we can hook into them to display a schedule of my dog Sycamore’s day.

    • 7 o’clock: Wake up, lick people’s faces, go on a walk
    • 8 o’clock: Eat
    • 9 o’clock: Go to sleep
    • 12 o’clock: Wake up, chew on something that she’s not supposed to chew on
    • 13 o’clock (1pm): Go to sleep
    • 16 o’clock (4pm): Wake up, bark at a squirrel, chase something only discernible to her
    • 17 o’clock (5pm): Eat, go on a walk
    • 18 o’clock (6pm): Go to sleep
    • 21 o’clock (9pm): Wake up, bother the cat, sniff random things all over the house
    • 22 o’clock (10pm): Go to sleep

    We already have our actions for each hour running (do_action('1_oclock'), etc), so all we have to do is hook into them. When we add an action like ‘Wake up’ into our 7_oclock action, we’re simply saying “When the 7_oclock action fires, run any of our code that is hooked into the 7_oclock action.

    In code, using WordPress actions, Sycamore’s schedule above looks like:

    // actions at 7_oclock (7am)
    add_action('7_clock', 'wake_up');
    add_action('7_oclock', 'lick_peoples_faces');
    add_action('7_oclock', 'go_on_walk');
    
    // actions at 8_oclock (8am)
    add_action('8_oclock', 'eat');
    
    // actions at 9_oclock (9am)
    add_action('9_oclock', 'sleep');
    
    // actions at 12_oclock (12pm)
    add_action('12_oclock', 'wake_up');
    add_action('12_oclock', 'chew_something_not_supposed_to');
    
    // actions at 13_oclock (1pm)
    add_action('13_oclock', 'sleep');
    
    // actions at 16_oclock (4pm)
    add_action('16_oclock', 'wake_up');
    add_action('16_oclock', 'bark_at_squirrel');
    add_action('16_oclock', 'chase_something_only_i_detect');
    
    // actions at 17_oclock (5pm)
    add_action('17_oclock', 'eat');
    add_action('17_oclock', 'go_on_walk');
    
    // actions at 18_oclock (6pm)
    add_action('18_oclock', 'sleep');
    
    // actions at 21_oclock (9pm)
    add_action('21_oclock', 'wake_up');
    add_action('21_oclock', 'bother_cat');
    add_action('21_oclock', 'sniff_randomly');
    
    // actions at 22_oclock (10pm)
    add_action('22_oclock', 'sleep');
    

    Let’s take a closer look at the 7am section:

    // actions at 7_oclock (7am)
    add_action('7_clock', 'wake_up');
    add_action('7_oclock', 'lick_peoples_faces');
    add_action('7_oclock', 'go_on_walk');
    

    At 7am, the first thing Sycamore does is wake up. The 'wake_up' part of add_action('7_oclock', 'wake_up'); is matched to a function of the same name: 'wake_up'. The following `wake_up()` function prints the words “Sycamore wakes up” onto the page:

    // output the text 'Sycamore wakes up';
    function wake_up() {
      echo 'Sycamore wakes up';
    }
    // add 'wake_up' to the '7_oclock' action
    add_action('7_clock', 'wake_up');
    
    // run all 7_oclock actions, including 'wake_up'
    // note: you likely will not be adding any do_action statements until you're writing plugins. You're far more likely to use add_action hooks
    do_action('7_oclock');
    

    Ordering Actions

    Great! Sycamore is awake! But… there are multiple things that are supposed to happen at 7 o’clock. How do we make sure that Sycamore doesn’t somehow lick people’s faces before she wakes up?

    We can give each action a priority number, with lower numbers running first. It’s like if you’re waiting in line: if you’re number 1 in line, you’ll go first. The default number for an action is 10. All of the actions above would have a priority of 10, because we didn’t specify any order.

    To make sure Sycamore wakes up before doing anything else, we give the 7 o’clock wake up action a priority of 1.

    // 1 means it will run before anything else
    add_action('7_clock', 'wake_up', 1);
    
    // not having a number means it defaults to a priority of 10
    // Sycamore needs a good round of lickin' everyone's faces after waking up
    add_action('7_oclock', 'lick_peoples_faces');
    
    // wake up: check
    // lick faces: check
    // time for a walk!
    add_action('7_oclock', 'go_on_walk', 20);
    

    Passing Arguments (values) to Actions

    If you have a dog, they might have a similar schedule. Let’s open this up to be available for any dog, not just Sycamore.

    To do this, the actions that run needs to know what dog is doing the action. We can do this by setting a PHP variable and passing it to the action function. Let’s go back to our do_action('7_oclock'); where we register the 7_oclock action that makes it available to hook into.

    // set the $dog_name to equal 'Sycamore'
    $dog_name = 'Sycamore';
    // pass $dog_name to our do_action. This makes $dog_name available to the functions that hook into this
    do_action('7_oclock', $dog_name);
    

    Now that we have a $dog_name variable, we can access it with our functions:

    // $dog_name should equal your dog's name
    function wake_up($dog_name) {
      // if $dog_name = 'Sycamore';
      // it outputs the text 'Sycamore wakes up';
      echo $dog_name.' wakes up';
    }
    // add 'wake_up' to the '7_oclock' action
    // 1 = the priority
    add_action('7_clock', 'wake_up', 1);
    

    So, if your $dog_name is “Fluffy,” then it would output “Fluffy wakes up.”

    Schedules can vary from day to day though. On Saturdays, Sycamore’s walk isn’t at 7am, it’s at 8am. A couple things we’d need to know before we can set the Saturday schedule correctly:

    • What day is it?
    • How to remove her 7am walk and add it in at 8am.

    First, let’s address how to get the $day in there. Back where we set the dog name, let’s add in the $day as well and pass it to the actions.

    $dog_name = 'Sycamore';
    // this will set $day to be the full name of the current day, like 'Saturday' or 'Sunday'
    $day = date('l');
    // pass $dog_name and $day to our do_action. This makes $dog_name and $day available to the functions that hook into this
    do_action('8_oclock', $dog_name, $day);
    

    Similarly to how action priorities default to 10 (the order that actions run), actions default to only having one variable. Now, since there are two variables ($dog_name and $day), we need to tell our actions that we’re using more than one variable. We’ll add our 8am action and make sure it has access to two variables.

    // $dog_name should equal your dog's name
    // $day will be the current day of the week
    function go_on_walk($dog_name, $day) {
      // if $day = 'Monday' and $dog_name = 'Sycamore, it will output: "Monday: Sycamore goes on a walk"
      echo $day. ': '. $dog_name.' goes on a walk';
    }
    
    // if today is Saturday
    if($day === 'Saturday') {
      // add 'go_on_walk' to the '8_oclock' action
      // 10 = the priority. We have to include it here so that we can also add the '2' for the number of arguments
      // 2 = the number of arguments ($dog_name and $day)
      add_action('8_oclock', 'go_on_walk', 10, 2);
    }
    

    Removing Actions

    The last thing we have to do is remove the 7 o’clock action because Sycamore doesn’t go on a walk at 7am and 8am on Saturdays. To do this, we use remove_action(). The one catch here is that we have to use remove_action() after the action we want to remove has already been added, otherwise there’s nothing to remove.

    // per usual, go on a walk at 7_oclock
    add_action('7_oclock', 'go_on_walk', 10, 2);
    
    // if today is Saturday, add in a walk on the 8_oclock action and remove the 7_oclock walk action.
    if($day === 'Saturday') {
      // add 'go_on_walk' to the '8_oclock' action
      add_action('8_oclock', 'go_on_walk', 10, 2);
      // remove the '7_oclock walk. We can do this since it was already added above
      remove_action('7_oclock', 'go_on_walk');
    }
    

    WordPress Action Summary

    We’ve gone over what actions in WordPress are. To summarize in a handy list for review:

    • WordPress has actions that run when the code runs the do_action('action_name') code.
    • You can add your own actions to run when the do_action('action_name') runs with add_action('action_name', 'your_function_name').
    • You can change the order of when actions run by passing a priority number like add_action('action_name', 'your_function_name', 1). 1 means it runs first. 10 is the default priority.
    • If an action has values/arguments that it passes, you can access those in the function you’re using by adding an argument number. If you need more than one argument (the default number), then you can specify the number of arguments you want. For example, to run get three arguments, you’d use add_action('action_name', 'your_function_name', 10, 3).
    • You can remove actions with remove_action('action_name', 'function_you_want_to_remove'), but the action has to have already been added in order to remove it.

    If you have any questions on what WordPress actions are or how to use them, feel free to ask in the comments. I’m planning to write a similar article on WordPress Filters, so be sure to follow me on Twitter if you want to know when I finish it!

  • Basic HTML Boilerplate Structure

    When you only create a new base template every few months (or longer!), it’s hard to remember the little details of the structure that you don’t touch often.

    As of HTML5, the <doctype>declaration and structure has gotten a lot easier, but it’s still easy to forget. Here’s the basics:

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <title>Page Title</title>
      <meta charset="utf-8" />
      <!-- other meta, CSS, and custom tags -->
    </head>
    
    <body>
      <header>Site Title</header>
    
      <main>
        <h1>Page Title</h1>
        <p>Body content</p>
      </main>
    
      <footer>Site Footer</footer>
      <!-- load JS here so it doesn't block the rendering of the page -->
    </body>
    </html>
    

    Notes on Easily Forgotten Structural Tags

    • <!DOCTYPE html>: Tells the browser/parser that the file is written in HTML.
    • <html lang=”en”>: Tells screen readers and search engines that the page is written in English. You can look up other language character codes.
    • <main>: Sets the main content for this page. This is generally what makes this page unique. For example, a news article would be wrapped in the HTML tag.

    Copy/Paste this boilerplate HTML and get going!

    Further Reading

  • Switch WordPress Database based on Git Branch

    I’m working on a large redesign project where lots of database changes are going to take place. In order to not mix-up the current master branch with the new redesign changes, I made a new database so I can keep things separate. The only trick is to remember to change out the database in wp-config.php when I switch branches.

    That’s not going to happen. I’ll definitely forget. Regularly.

    Fortunately, you can grab the branch you’re on via php with a bit of code from user program247365 on stackoverflow.

    I took that and added a bit to choose the database I want based on the branch I’m on. You’ll need to change out the $db_name and $branch variables to match your own, then you’ll be good to go!

    // get branchname
    function config_get_git_branch() {
        // This assumes you have your .git directory at the same level as wp-config.php.
        // If you don't, then change the path to wherever your .git director is
        $stringfromfile = file('.git/HEAD', FILE_USE_INCLUDE_PATH);
    
        $firstLine = $stringfromfile[0]; //get the string from the array
    
        $explodedstring = explode("/", $firstLine, 3); //seperate out by the "/" in the string
    
        $branch = $explodedstring[2]; //get the one that is always the branch name
    
        return trim($branch);
    }
    
    // choose which db you want to use
    function config_get_db_name() {
        $branch = config_get_git_branch();
    
        // change these $db_name and and $branch strings to match
        // whatever ones you want.
        if($branch === 'child') {
            $db_name = 'child_db';
        } else {
            $db_name = 'site_db';
        }
        return $db_name;
    }
    
    // ** MySQL settings - You can get this info from your web host ** //
    /** The name of the database for WordPress */
    define('DB_NAME', config_get_db_name());
    

    Now you’ll never forgot to switch the DB out when you checkout to a new branch. Happy coding!

  • Import a Huge Database with MySQL Command Line in MAMP

    Import a Huge Database with MySQL Command Line in MAMP

    I needed to import a 500mb MySQL database today, and I didn’t want to mess with changing the max 32mb upload file size with phpmyadmin. The 32mb limit is due to having to upload and process the file, but if the file is on your local machine anyways, there’s no need to upload it. Let’s bypass the upload limit and import the database using the MySQL command line.

    Start up MAMP, open terminal, and enter:

    $ /Applications/MAMP/Library/bin/mysql --host=localhost -uroot -proot
    

    This will put you into a kind of MySQL shell. Now you can run a few basic commands to test it out.

    ## List all the databases
    $ show databases;
    
    ## It outputs a pretty ASCII drawing for your tables
    +-------------------------+
    | Database                |
    +-------------------------+
    | my_database             |
    | another_db              |
    | etc_db                  |
    +-------------------------+
    3 rows in set (0.00 sec)
    

    To import a new database, find the path to your MySQL database file, and run these commands:

    ## Create a new database if you haven't yet
    $ CREATE DATABASE my_db_name
    
    ## Move into the database, kind of like the `cd` command to switch directories in terminal
    $ use my_db_name
    
    ## Import the database
    $ SET autocommit=0 ; source /path/to/database/my_mysql_database.sql ; COMMIT ;
    

    Now you’ll see a bunch of queries whiz by. Once you see the command line ready for another prompt, you’re good to go!

  • Terminal Command for Looking up Nameservers

    At The Engaging News Project, we recently upgraded our DNS hosting by moving over to Cloudflare. I wanted to test our site as soon as the nameservers updated to Cloudflare’s to make sure no weird issues popped up.

    Fortunately, there’s a handy terminal command for that!

    $ nslookup -type=ns jeremyjon.es
    

    nslookup is a command to query nameservers and get all kinds of info back related to the server it’s on and any DNS settings you want to… look-up. Pretty well named command, I guess.

    In our case, the nslookup -type=ns jeremyjon.es command will return all the nameservers of my site, jeremyjon.es.

    As of this writing, here’s the response for my domain.

    $ nslookup -type=ns jeremyjon.es
    
    Server:		8.8.8.8
    Address:	8.8.8.8#53
    
    Non-authoritative answer:
    jeremyjon.es	nameserver = ns3.dreamhost.com.
    jeremyjon.es	nameserver = ns1.dreamhost.com.
    jeremyjon.es	nameserver = ns2.dreamhost.com.
    

    To get different information about your DNS, like CNAME, MX, A Records, etc, just change out the ns part of -type=ns with the record type you’re looking for:

    $ nslookup -type=cname jeremyjon.es 
    $ nslookup -type=a jeremyjon.es 
    $ nslookup -type=mx jeremyjon.es 
    

    There’s plenty more nslookup can do that I imagine I’ll never, ever use as a front-end developer, but I’m glad it’s there if I need it.

    Clearing out DNS

    If you just made a DNS change and want to flush your cache to try to grab the updated nameservers and you’re on OS X 10.10.4 or above, use:

    sudo killall -HUP mDNSResponder
    

    Switching servers of any kind is stressful. Hopefully these commands will help your heart beat a little easier when making the switch.

  • Apple Bug Report – Non-native Focusable Elements Page Jump

    On iOS devices running Safari on version 10+, when focusing a non-native focusable element (ie – a div that is focusable via JavaScript or with a tabindex value) inside an embedded iframe on a page, the parent page will jump down the page and you have to scroll back up to return to the focused element.

    To reproduce, it,

    1. Use your iOS device on version 10+ and click the slider handle in the embedded quiz.
    2. When you click the handle to give it focus, the page will jump down and you’ll have to scroll back up to return to the slider.

    This is just a post to explain my bug report to Apple developers and any other devs who may be experiencing a similar issue. For more details, read this Stack Overflow question on this bug.

  • How to Fix Blurry Images in WordPress 4.4 from srcset and sizes

    In WordPress 4.4 they added a big feature: responsive images using srcset and sizes for all content images.

    This is amazing. Since WordPress is a hugely popular framework, the amount of bandwidth saved is astronomical. I’m really proud of the WordPress team for implementing this.

    But… there are some blurry images. It’s not a perfect one-size fits all solution for every site.

    If your images are full screen width, you’ll get a blurry image on wide screens because WordPress is telling your browser to use an image smaller than your browser width. It’s a simple fix, and if you don’t want to read my mini-rant, you can skip to the fix.

    The Backwards Way To Fix It

    When I was googling to see what others have done to fix this, the only answer I was coming across was to entirely remove the srcset responsive image approach. Go back to a plain ol’ img tag, thank you very much.

    I get it. Images are much easier that way. But I don’t think the importance of what srcset accomplishes was understood.

    When you use srcset with your image, you provide your browser with a bunch of different versions of your image from small ones to giganto ones. When you go to your site, your browser quickly scans the list of images and picks out the one it needs. That way you don’t download a 2000px wide desktop image onto your phone. You download the 400px one. When you’re paying for your data usage, that’s a big deal.

    So, if you’re getting blurry images in WordPress, don’t throw the baby out with the bath water.

    The Fix

    Here’s a snippet to drop into your functions.php file that will keep the benefits of srcset responsive images and never give you a blurry image. It won’t be a fine-tuned, Italian leather, srcset machine, but it’s far better than axing it entirely.

    function osteo_img_sizes($sizes) {
    	return '100vw';
    }
    add_filter( 'wp_calculate_image_sizes', 'osteo_img_sizes');
    

    This filter overrides WordPress’s default sizes attribute to tell your browser, “Don’t serve images larger than the screen width.” VW here stands for viewport width (your browser width).

    That’s it. It’s not perfect, but it serves the people that need it most: people on mobile devices with a slow and/or costly connection.

  • Using BEM in the Wild

    BEM can get out of control if you’re not careful. On the first project I used BEM, I handcrafted this artisanal class name: .progress__bar__question-count__current-number.

    Yup. That’s four levels deep. I’m not proud of this.

    The goal of this article is to make sure another .progress__bar__question-count__current-number never gets written. Before we dive in, if you’re not familiar with the BEM naming convention, head over to B is for Block: An Intro to the BEM Naming Convention. Don’t worry, I’ll wait until you’re done.

    Ready? Good. Here we go!

    It’s BEM, not BEEEEM

    Be as descriptive as you need to be with your BEM class names to avoid duplication and confusion. Sure, my .progress__bar__question-count__current-number class lets me know that current-number is nested 4 levels deep in the HTML, but is that worth the verbosity?

    Nope.

    It means more changes to make in your CSS when you modify the HTML. Rather than duplicate your HTML structure, be descriptive and unique.

    When I refactor, .progress__bar__question-count__current-number will become .progress-bar__current-number.

    Ah. Much better.

    “The best is the enemy of the good.” – Voltaire

    I can get stuck in a pattern of trying to find the perfect solution rather than an easy one that accomplishes the task. As the saying goes, “Don’t let perfect be the enemy of good.” That’s when .progress__bar__question-count__current-number rears its ugly head.

    Remember, BEM is a convention to make your code easier to maintain. If it’s not making your code easier to maintain, modify it. BEM is a tool for you to use, not vice-versa.

    If a Block is Within Another Block, Mix It

    One of the great things about BEM is the flat class structure. You don’t have to nest anything in SASS or use multiple class names to win a specificity battle.

    That’s great… until a block is nested inside another block. Let’s say you have a .card block that has a .list and a .button inside it. What do you do? Do you duplicate the entire block again with the block name prefixed? That’s the only way to keep it 100% perfect and flat. So, should we do this?

    <article class='card'>
      <div class='card__header'>
        <h2 class='card__title'>B is for Block: How to BEM</h2>
      </div>
      <div class='card__content'>
        <ol class='list card__list'>
          <li class='list__item card__list__item'>
            Describe the Main Block with a word or two.
          </li>
        </ol>
        <a class='button button--with-icon card__button card__button--button-with-icon'>
          <span class='button__text card__button__text'>
            Read More
          </span>
        </a>
      </div>
    </article>
    

    No! Don’t put BEM in your BEM. That’s what leads you down the crooked path to .progress__bar__question-count__current-number! Heed my warning. Don’t do it. Nest the components, but mix the class names, and let your specificity win out with the nested class names. Like this:

    <article class='card'>
      <div class='card__header'>
        <h2 class='card__title'>B is for Block: How to BEM</h2>
      </div>
      <div class='card__content'>
        <ol class='list card__list'>
          <li class='list__item'>
            Describe the Main Block with a word or two.
          <li>
        </ol>
        <a class='button button--with-icon card__button'>
          <span class='button__text'>
            Read More
          </span>
        </a>
      </div>
    </article>
    

    Here’s the above example in a CodePen that highlights the components and displays the class names that go with it:

    See the Pen BEM Syntax Visualized by Jerry Jones (@jeryj) on CodePen.

    //assets.codepen.io/assets/embed/ei.js

    You might encounter a time where it’s helpful to put your BEM in your BEM a little bit, but be careful with it. Remember, BEM is supposed to be helpful to you and your team. Feel free to “modify” it.

    See what I did there?

    Blocks Don’t Care About Other Blocks… Until They Move In

    You have a .friend. They’re a good .friend, but sometimes they do things you don’t agree with. Nothing wrong with that.

    You have .your-house. You like your .friend and .your-house doesn’t care about what your .friend does. They can go wherever they want. Do what they want to do.

    Until your .friend gets kicked out. They need a place to stay.

    Enter, .your-house. But when your .friend is living with you, they’re going to need to follow your rules. .friend has to realize that now, they’re also .your-house__friend.

    // home sweet home!
    .your-house {
        laundry: clean;
        dishes: clean;
    }
    
    // do what you want! be you!
    .friend {
        laundry: dirty;
        dishes: dirty;
        goes-out: tons;
        pays-rent: nope;
        demeanor: nice;
        fun: yes;
    }
    
    // Uh oh. Gotta set some rules while
    // they're living in your house
    .your-house__friend {
        laundry: clean;
        dishes: clean;
        pays-rent: yes;
    }
    

    Blocks don’t care about other blocks. That’s what makes them maintainable and predictable. When you put a block inside another block, the parent block is the one that cares. .friend doesn’t care that it’s in .your-house. .your-house is the one that cares, so it sets the rules on .your-house__friend.

    Be a good .friend and keep .your-house class names tidy.

    The BEM Cheatsheet

    Here’s the cheatsheet of the tips for actually using BEM.

    1. Formatting: .block__element--modifier
    2. Describe the block with a word or two. If it’s two words, separate them with just one dash or do camelCase or whatever. Doesn’t really matter. Just be consistent and document it.
    3. Describe the __element with a word or two.
    4. Add --modifiers if necessary.
    5. Avoid lots of __elements unless you can’t avoid it. For example, .card__title__link__progress__icon is a little excessive.
    6. You can mix classnames that are parts of two blocks. For example, if it’s a .button block, but it’s also a .card__button element, you can use both in the HTML.

    That’s it. You should know enough to confidently use BEM and avoid common traps. You’ll still come across scenarios that you’re not sure what to do. We all do. If you have any questions or think I made a mistake, let me know at @juryjowns.