$30 off During Our Annual Pro Sale. View Details »

Don't Fear the Custom Theme: How to build a custom WordPress theme with only four files

Don't Fear the Custom Theme: How to build a custom WordPress theme with only four files

Slides for my talk at WordCamp Toronto 2014. The full theme is available here: https://github.com/LinnAlexandra/wcto14

I updated this talk in 2016 for WordCamp Montréal: https://speakerdeck.com/linnalexandra/dont-fear-the-custom-theme-how-to-build-a-custom-wordpress-theme-with-only-four-files-1

Linn Øyen Farley

November 15, 2014
Tweet

More Decks by Linn Øyen Farley

Other Decks in Programming

Transcript

  1. Don’t Fear the Custom
    Don’t Fear the Custom
    Theme
    Theme
    How to build a custom WordPress theme with
    How to build a custom WordPress theme with
    only four files
    only four files
    Linn Øyen Farley
    / @LinnOyenFarley
    drollic.ca

    View Slide

  2. Linn Øyen Farley
    Linn Øyen Farley
    Web designer/developer
    Building things on the internet since 2005
    Usually working solo or with a designer
    Mainly use WordPress for client sites

    View Slide

  3. I ♥ WordPress
    I ♥ WordPress
    Amazing community and resources
    Active plugin community (don’t have to re-invent the wheel)
    Super easy to hand off to clients

    View Slide

  4. But ...
    But ...
    “WordPress outputs bloated code”
    “All WordPress sites look the same”
    and/or
    “I don’t have time to learn PHP”
    “I tried customizing a [commercial theme provider] theme once and I couldn’t find
    anything”

    View Slide

  5. This talk
    This talk
    is a file-by-file guide to creating a fully-functional WordPress theme, based on an
    existing HTML/CSS design
    gives an overview of the bare minimum of PHP functions needed to build a WordPress
    theme (plus some extra stuff)
    suggests how you could use a custom WordPress theme as a tool for rapid prototyping
    uses WordPress.org’s Theme Guidelines (
    ) as a starting point for best practices
    make.wordpress.org/themes/handbook
    /guidelines/

    View Slide

  6. This talk won’t
    This talk won’t
    cover HTML/CSS/design principles
    100% accurately represent how I build themes for clients
    focus on making a WordPress.org-repository-ready theme and/or incorporate every use
    case into a single theme
    be a hands-on workshop — I have less than an hour, so I’ll be moving pretty quickly

    View Slide

  7. Commercial theme
    Commercial theme
    Full disclosure: I installed this exact theme on a client’s site earlier this year. There is definitely a place for commercial and child themes in the
    WordPress ecosystem, but creating a custom theme may be appropriate more often than you think.

    View Slide

  8. Recent theme for a client
    Recent theme for a client
    404.php
    comments.php
    footer.php
    functions.php
    header.php
    images/
    logo.png
    nav-icon.png
    search.png
    index.php
    js/
    html5shim.js
    respond.min.js
    page.php
    screenshot.png
    searchform.php
    style.css

    View Slide

  9. Theme for WordPress.org
    Theme for WordPress.org
    index.php
    screenshot.png
    style.css
    Note: The recommended theme guidelines ( ) include a few more files,
    but the three above are the only required files ( ).
    make.wordpress.org/themes/handbook/guidelines/theme-check/#recommended
    make.wordpress.org/themes/handbook/guidelines/theme-check/#required
    ...plus we’ll talk about functions.php, because it’s my favourite

    View Slide

  10. Wait a minute...
    Wait a minute...
    How can this →
    be successfully reduced to this:
    index.php
    screenshot.png
    style.css
    (you might be wondering)

    View Slide

  11. The template hierarchy
    The template hierarchy
    Reference: codex.wordpress.org/Template_Hierarchy

    View Slide

  12. The template hierarchy
    The template hierarchy
    For our purposes, the most important part of that giant diagram is on its
    right-hand side: all arrows lead to index.php.
    If your theme contains the other files on the diagram, they will trump
    index.php, but if you only have index.php, that’s fine too!

    View Slide

  13. List of requested features
    List of requested features
    Responsive design
    Homepage with intro paragraph and latest post
    About page with image gallery
    Blog with widgets in the sidebar

    View Slide

  14. WordPress dashboard tasks
    WordPress dashboard tasks
    Pages → Add New:
    Home (the intro paragraph), About (the image gallery), and Blog (with no content)
    Posts → Add New:
    create a few blog posts
    Settings → Reading:
    Choose “Front page displays: A static page”
    Make Home your “Front page” and Blog your “Posts page”
    Appearance → Menus:
    Create a main navigation menu with the pages you’ve made

    View Slide

  15. File #1:
    File #1:
    screenshot.png
    screenshot.png

    View Slide

  16. Start with a design
    Start with a design
    Here’s a design ready to go, built in HTML and CSS. The image below covers your first
    required file, screenshot.png.
    Recommended size: 880x660px
    Should be a “reasonable facsimile” of the theme after it is initially activated with default
    options
    Reference: make.wordpress.org/themes/handbook/guidelines/theme-check/#required

    View Slide

  17. View Slide

  18. File #2:
    File #2:
    style.css
    style.css

    View Slide

  19. Get your stylesheet ready
    Get your stylesheet ready
    Make sure your CSS file is called style.css, and that it starts with the following comment:
    /*
    Theme Name: [Client's Name]
    Description: Custom theme for [Client's Name].
    Author: Linn Oyen Farley
    Author URI: http://drollic.ca
    Version: 1.0
    */
    The absolute minimum you need to include here is your theme’s name, but why not give
    yourself some credit?
    Reference: codex.wordpress.org/Theme_Development#Theme_Stylesheet

    View Slide

  20. Include WordPress-specific classes
    Include WordPress-specific classes
    WordPress auto-generates a few classes, which you can include if you want to style them:
    /* Image alignment classes */
    .aligncenter {}
    .alignleft {}
    .alignright {}
    /* Image caption-related classes */
    .wp-caption {}
    .wp-caption-text {}
    .gallery-caption {}
    /* Post and comment classes */
    .sticky {}
    .bypostauthor {}
    /* Menu classes */
    .current_page_item, .current_page_parent {}

    View Slide

  21. File #3:
    File #3:
    index.php
    index.php

    View Slide

  22. Move from HTML to PHP
    Move from HTML to PHP
    Take your index.html file...

    ...and save it as index.php.


    That’s all you need to do to start writing PHP in the file. Most WordPress theme files
    consist of a lot of HTML and a bit of PHP.

    View Slide

  23. Interlude:
    Interlude:
    Intro to PHP
    Intro to PHP

    View Slide

  24. Things to keep in mind:
    Things to keep in mind:
    PHP isn’t as forgiving as HTML or CSS
    Mistakes in your code = white screen of death + (sometimes) error messages
    You only need to know a little PHP syntax to build WordPress themes
    Use a code editor with syntax checking, or run your code through a validator like
    PHPCodeChecker.com

    View Slide

  25. Always:
    Always:
    enclose PHP with opening () tags
    decide to use either single or double quotes
    mind your semicolons




    Reference: php.net/manual/en/index.php

    View Slide

  26. Conditionals
    Conditionals
    if ( condition1 ) {
    if condition #1 is true, do thing #1
    } elseif ( condition2 ) {
    otherwise, if condition #2 is true, do thing #2
    } else {
    or, if none of those conditions are true, do thing #3
    }
    don’t forget the closing curly brace!
    Reference: Conditional statements: php.net/manual/en/language.control-structures.php

    View Slide

  27. Operators
    Operators
    && (and)
    || (or)
    == (is equal to)
    != (is not equal to)
    References:
    Logical operators:
    Comparison operators:
    php.net/manual/en/language.operators.logical.php
    php.net/manual/en/language.operators.comparison.php

    View Slide

  28. Loops
    Loops
    while ( condition1 ) { }
    The while loop starts with a condition, and then specifies what to do as long as that
    condition is true.
    For example, the main posts loop in WordPress states that as long as there are posts to
    show (while you have posts), set up each post (so you can grab its title, content, etc).
    Reference: php.net/manual/en/control-structures.while.php

    View Slide

  29. Variables
    Variables
    $ indicates a variable, either one that you want to store or one that is already stored
    $myNewVariable = 'This variable should contain some text!';
    $myNewVariable now contains that string of text, which you can use later.
    Reference: php.net/manual/en/language.variables.basics.php

    View Slide

  30. Variables
    Variables
    echo is used to display/output the contents of an existing variable
    This:

    would output your text string on the page:
    This variable should contain some text!
    Reference: php.net/manual/en/function.echo.php

    View Slide

  31. Conditional tags
    Conditional tags
    WordPress has lots of its own functions that you can use in your theme’s conditional
    statements.
    I’m going to cover these ones:
    is_front_page()
    true if you’re viewing the front page
    is_page()
    true if you’re viewing a single page
    is_single()
    true if you’re viewing a single post
    Reference: codex.wordpress.org/Conditional_Tags

    View Slide

  32. Back to file #3:
    Back to file #3:
    index.php
    index.php

    View Slide

  33. wp_title()
    wp_title()
    Replace the contents of with wp_title().
    This will output a separator and the title of the page or post being viewed.
    If you’re viewing the front page, it won’t output anything.
    Reference: codex.wordpress.org/Function_Reference/wp_title

    View Slide

  34. wp_title() in action
    wp_title() in action
    Replacing this:
    Feline Design Co.
    with this:

    outputs this (when viewing the blog post with this title):
    » Blog post #1

    View Slide

  35. wp_title() & bloginfo('name')
    wp_title() & bloginfo('name')
    The title function looks best if you also add the site’s name (the one you specify under
    Settings → General), and change the separator. This:

    changes the separator to a long dash, moves it to the right-hand side, and adds the site
    name, outputting this (when viewing that same blog post):
    Blog post #1 — Feline Design Co.
    Reference: codex.wordpress.org/Function_Reference/bloginfo

    View Slide

  36. wp_head() & wp_footer()
    wp_head() & wp_footer()
    These required tags always need to be included in your theme. They go immediately
    before your closing head tag and your closing body tag, respectively:





    View Slide

  37. language_attributes() & bloginfo('charset')
    language_attributes() & bloginfo('charset')
    You can dynamically specify the site’s language and character set using these functions.
    This:
    >


    outputs something like this:



    Reference: codex.wordpress.org/Function_Reference/language_attributes

    View Slide

  38. bloginfo('template_directory')
    bloginfo('template_directory')
    Replace all relative links to design elements (such as your logo in the header area) with
    links to those elements in your theme folder.
    You can use the same bloginfo() function you used earlier to get your theme’s location.
    Instead of asking for bloginfo('name') or bloginfo('charset'), ask for
    bloginfo('template_directory').

    View Slide

  39. bloginfo('template_directory') in action
    bloginfo('template_directory') in action
    Replacing this:

    with this:

    outputs this:

    View Slide

  40. wp_nav_menu()
    wp_nav_menu()
    Replace your static navigation menu with the WordPress native menu (the one you can
    create under Appearance → Menus).
    Make a note of whatever you put as the theme location here, because you’ll need it later!
    Reference: codex.wordpress.org/Function_Reference/wp_nav_menu

    View Slide

  41. wp_nav_menu() in action
    wp_nav_menu() in action
    Replacing this:

    Home
    About
    Blog

    with this:
    'main-nav'); ?>
    Make a note of “main-nav” for later!

    View Slide

  42. wp_nav_menu() in action
    wp_nav_menu() in action
    ...outputs something like this:


    About
    Blog
    Home


    Until you assign a menu to the “main-nav” theme location, wp_nav_menu() will default to
    an alphabetical list of your pages.

    View Slide

  43. The WordPress loop
    The WordPress loop
    Replace your hard-coded content with dynamic content. Start by checking if any content
    exists, and display an error message if it doesn’t:

    Not Found
    Sorry, nothing found.

    View Slide

  44. Anatomy of an if statement
    Anatomy of an if statement
    A basic if statement is structured like this:
    the word if
    1.
    opening parenthesis
    2.
    condition
    3.
    closing parenthesis
    4.
    opening curly brace
    5.
    things that should happen if the condition is true
    6.
    closing curly brace
    7.

    View Slide

  45. have_posts()
    have_posts()

    Not Found
    Sorry, nothing found.

    have_posts() is a WordPress function that checks if there is any content to display
    (either posts or pages).
    The ! means not, i.e. if there is not any content, do the following — in this case, display a
    “Not Found” heading and message.
    Reference: codex.wordpress.org/Function_Reference/have_posts

    View Slide

  46. The WordPress loop
    The WordPress loop
    If there is stuff to show, however, it should display:

    Not Found
    Sorry, nothing found.
    // Display the content!
    } // end if ?>

    View Slide

  47. Anatomy of an if/else statement
    Anatomy of an if/else statement
    When you want different stuff to happen when your condition is true vs. when it is not true,
    the if statement needs a few extra parts after the closing curly brace:
    the word else
    1.
    opening curly brace
    2.
    things that should happen if the condition is not true
    3.
    closing curly brace
    4.

    View Slide

  48. The WordPress loop
    The WordPress loop
    while ( have_posts() ) {
    the_post(); ?>

    } // end while
    If you do have content, start a while loop to display it.
    This states that as long as there is content to show, set up the_post(). the_post()
    function contains all of the info about a post or page in WordPress, so it’s ready for you to
    grab and use.
    Reference: codex.wordpress.org/Function_Reference/the_post

    View Slide

  49. the_title() & the_content()
    the_title() & the_content()

    the_title() will pull whatever you’ve put in the post or page title field. WordPress
    doesn’t automatically format your title, so you need to wrap the PHP tag in some HTML to
    style it.

    the_content() pulls everything from the main content editing box in WordPress,
    formatting and all.
    References:
    codex.wordpress.org/Function_Reference/the_title
    codex.wordpress.org/Function_Reference/the_content

    View Slide

  50. Recap: the full loop
    Recap: the full loop
    Here is the loop in its entirety, with comments throughout:
    // If we do not have content...
    if ( ! have_posts() ) {
    // ...then show an error message: ?>
    Not Found
    Sorry, nothing found.
    // Otherwise...
    } else {
    // ...as long as there is content to show...
    while ( have_posts() ) {
    // ...set up each piece of content so we can grab stuff from it:
    the_post(); ?>

    } // end while
    } // end if ?>

    View Slide

  51. Theme test drive
    Theme test drive
    At this point, regular pages look almost perfect:

    View Slide

  52. Theme test drive
    Theme test drive
    You still need to set up a menu location to get those
    menu items in the right order, but I’ll cover that
    when we get to functions.php.

    View Slide

  53. Theme test drive
    Theme test drive
    Our error page is also functioning well:

    View Slide

  54. Theme test drive
    Theme test drive
    The blog page needs some additional info on each post, beyond just the title and content.
    It also needs a widgetized sidebar:

    View Slide

  55. Theme test drive
    Theme test drive
    Our single blog posts need additional info and a sidebar too, plus a section for comments:

    View Slide

  56. Theme test drive
    Theme test drive
    Finally, the homepage shouldn’t display the_title(), and it’s missing the latest post at
    the bottom:

    View Slide

  57. is_front_page()
    is_front_page()
    Once you’ve established that you do have content to show, start by checking whether
    you’re viewing the front page.
    If you are, display the content without the title:
    the_content();
    } // end if ?>
    Reference: codex.wordpress.org/Function_Reference/is_front_page

    View Slide

  58. WP_Query()
    WP_Query()
    To grab the latest post and display it on the front page, you can use the function
    WP_Query(). First, store the result (if there is one) in a variable:

    Reference: codex.wordpress.org/Class_Reference/WP_Query

    View Slide

  59. WP_Query()
    WP_Query()
    Then you can use the same have_posts() function you’ve already seen, but apply it
    specifically to your $latestPost variable. This double-checks that there is a post to
    show, before adding a “Latest from the blog” heading and setting up the_post():
    have_posts() ) {
    // If there is a post to show, add a title before starting the loop: ?>
    Latest from the blog...
    have_posts() ) {
    $latestPost->the_post();
    } // end while
    } // end if ?>

    View Slide

  60. the_excerpt()
    the_excerpt()
    If there is a post to show, you can use the_title() again to display its title.
    Instead of displaying the full content of the post, only display its excerpt by using the
    function the_excerpt():


    Reference: codex.wordpress.org/Function_Reference/the_excerpt

    View Slide

  61. the_permalink()
    the_permalink()
    the_permalink() will get the post’s URL/permalink, so you can make the post title link
    to the full post:

    Reference: codex.wordpress.org/Function_Reference/the_permalink

    View Slide

  62. the_time()
    the_time()
    Add the date and time the post was published, using the_time() and the Codex’s date
    and time formatting cheatsheet ( ). This:
    codex.wordpress.org/Formatting_Date_and_Time
    Posted on at
    outputs this:
    Posted on November 15th 2014 at 8:00 AM
    Reference: codex.wordpress.org/Template_Tags/the_time

    View Slide

  63. the_terms()
    the_terms()
    Add the post’s categories by using the_terms(). This:
    in ID, 'category' ); ?>
    outputs this:
    in Cats, Design
    Reference: codex.wordpress.org/Function_Reference/the_terms

    View Slide

  64. Recap: latest post
    Recap: latest post
    Here’s the complete block of code to display the post’s permalink, title, metadata, and
    excerpt:

    Posted on at in $post->ID, 'category' ); ?>

    And this is how it looks:

    View Slide

  65. Homepage: complete!
    Homepage: complete!

    View Slide

  66. is_page()
    is_page()
    You can use the same code to display each post’s metadata on the main blog page and
    on single posts.
    But first, to avoid displaying it on pages, add another condition to the loop:
    // If this is a regular page, just display the title and content: ?>

    } else {
    // Otherwise, display the title and content plus the metadata ?>

    Posted on at in $post->ID, 'category' ); ?>
    } // end if ?>
    Reference: codex.wordpress.org/Function_Reference/is_page

    View Slide

  67. comments_template()
    comments_template()
    To avoid having comments display on pages, add the comments template at the end of
    the loop, after you’ve established that you’re not viewing a page:
    Posted on at in $post->ID, 'category' ); ?>
    comments_template(); ?>
    Reference: codex.wordpress.org/Function_Reference/comments_template

    View Slide

  68. comments_template() in action
    comments_template() in action

    View Slide

  69. next_posts_link() & previous_posts_link()
    next_posts_link() & previous_posts_link()
    Once you have more posts than “Blog pages show at most” (under Settings → Reading),
    you’ll need pagination links to navigate the blog.
    Add the following code between the_content() and comments_template():


       


    References:
    codex.wordpress.org/Function_Reference/next_posts_link
    codex.wordpress.org/Function_Reference/previous_posts_link

    View Slide

  70. next_posts_link() & previous_posts_link() in
    next_posts_link() & previous_posts_link() in
    action
    action
    Depending on where you are in the blog, these links may look like any of the following
    examples:

    View Slide

  71. Saving space for widgets
    Saving space for widgets
    You’ll be creating a widgetized area in functions.php, so save some space for it now.
    Before you start the loop, make sure you’re not on a page, and then start the primary
    section:




    View Slide

  72. Saving space for widgets
    Saving space for widgets
    Then just before closing the main section, check to make sure you’re not on a page
    again, and add an aside:







    Make a note of “blog-widget-area” for later!
    Reference: codex.wordpress.org/Function_Reference/dynamic_sidebar

    View Slide

  73. Saving space for widgets
    Saving space for widgets
    For now, this will give you an empty sidebar area on the blog and on single posts:

    View Slide

  74. is_single()
    is_single()
    Post titles should appear slightly differently on single posts vs. on the main blog page.
    Inside the final else statement, add one more conditional statement to take care of this:
    if ( is_single() ) {
    // If you're viewing a single post, display the title as an h1: ?>

    // Otherwise, display the title as an h3 and link it to the full post: ?>


    Posted on at in $post->ID, 'category' ); ?>

    Reference: codex.wordpress.org/Function_Reference/is_single

    View Slide

  75. File #4:
    File #4:
    functions.php
    functions.php

    View Slide

  76. Not required, but super useful
    Not required, but super useful
    This file is a plugin bundled with your theme. It can add lots of functionality to your site,
    but keep in mind that it will all disappear if you switch your theme.
    There are so many things you can do with a functions.php file, and I have very little time,
    so I’m just going to cover a few examples of what’s possible.

    View Slide

  77. Create your functions file
    Create your functions file
    Make a new file called functions.php, and add opening and closing PHP tags:
    ?>

    View Slide

  78. register_nav_menus()
    register_nav_menus()
    Remember making a note of “main-nav”, when you were replacing your hard-coded menu
    with wp_nav_menu()?
    It’s time to create that menu location, so you can assign your menu to it under Appearance
    → Menus:
    // Register menu(s)
    register_nav_menus(
    array(
    'main-nav' => 'Main Navigation'
    )
    );
    Reference: codex.wordpress.org/Function_Reference/register_nav_menus

    View Slide

  79. register_nav_menus()
    register_nav_menus()
    If your theme is going to use more than one menu, you can register them all in one go:
    // Register menu(s)
    register_nav_menus(
    array(
    'main-nav' => 'Main Navigation',
    'footer-nav' => 'Footer Navigation'
    )
    );
    To display the menu assigned to Footer Navigation (under Appearance → Menus), add the
    code below to index.php:
    'footer-nav'); ?>

    View Slide

  80. register_nav_menus() in action
    register_nav_menus() in action
    Ahhhh. Much better.
    (Note: you need to go to Appearance → Menus in the WordPress dashboard, create a menu, and
    select Main Navigation as its Theme location for this to work.)

    View Slide

  81. register_sidebar()
    register_sidebar()
    Although the word “sidebar” is right there, this is how you create any widgetized area, i.e.
    areas that you can drag widgets into under Appearance → Widgets.
    References:
    (writes the code for you)
    codex.wordpress.org/Function_Reference/register_sidebar
    generatewp.com/sidebar/
    // Register widgetized area(s)
    function my_widgets_init() {
    register_sidebar(
    array(
    'id' => 'blog-widget-area',
    'name' => 'Blog Widget Area',
    'description' => 'Appears on the blog and single posts.',
    'before_title' => '',
    'after_title' => '',
    'before_widget' => '',
    'after_widget' => '',
    )
    );
    }
    add_action( 'widgets_init', 'my_widgets_init' );

    View Slide

  82. register_sidebar()
    register_sidebar()
    Remember “blog-widget-area”? Whatever you put as the ID in functions.php:
    'id' => 'blog-widget-area'
    needs to match what you put in dynamic_sidebar() in index.php:

    View Slide

  83. register_sidebar()
    register_sidebar()
    You can register several widget areas in one go with this function, and then display each
    one using dynamic_sidebar('the-id-you-chose'):
    // Register widgetized area(s)
    function my_widgets_init() {
    register_sidebar(
    array(
    'id' => 'blog-widget-area',
    'name' => 'Blog Widget Area',
    'description' => 'Appears on the blog and single posts.',
    'before_title' => '',
    'after_title' => '',
    'before_widget' => '',
    'after_widget' => '',
    )
    );
    register_sidebar(
    array(
    'id' => 'footer-widget-area',
    'name' => 'Footer Widget Area',
    'description' => 'Appears in the footer.',
    'before_title' => '',
    'after_title' => '',
    'before_widget' => '',
    'after_widget' => '',
    )
    );
    }
    add_action( 'widgets_init', 'my_widgets_init' );

    View Slide

  84. register_sidebar() in action
    register_sidebar() in action
    We have a sidebar!
    (Note: you need to go to Appearance → Widgets in the WordPress
    dashboard, and drag widgets into the area called Blog Widget Area
    for this to work.)

    View Slide

  85. wp_enqueue_scripts
    wp_enqueue_scripts
    Instead of including stylesheets in the of your site:


    register and then enqueue them in functions.php:
    // Register and enqueue styles and scripts
    function my_scripts_and_styles() {
    wp_register_style( 'core', get_stylesheet_uri(), false, '1.0', 'all' );
    wp_register_style( 'fonts', 'http://fonts.googleapis.com/css?family=Montserrat', false, '1.0', 'all' );
    wp_enqueue_style( 'core' );
    wp_enqueue_style( 'fonts' );
    }
    add_action( 'wp_enqueue_scripts', 'my_scripts_and_styles' );
    Reference: codex.wordpress.org/Plugin_API/Action_Reference/wp_enqueue_scripts

    View Slide

  86. wp_register_style()
    wp_register_style()
    This registers the theme’s default stylesheet:
    wp_register_style( 'core', get_stylesheet_uri(), false, '1.0', 'all' );
    get_stylesheet_uri will grab the URL of style.css. This stylesheet has no
    dependencies on other CSS files to function, it’s at version 1.0, and it should be loaded on
    all media (as opposed to just “screen” or “print”).
    References:
    (writes the code for you)
    codex.wordpress.org/Function_Reference/wp_register_style
    generatewp.com/register_style/

    View Slide

  87. wp_register_style()
    wp_register_style()
    This line registers a Google Fonts stylesheet:
    wp_register_style( 'fonts', 'http://fonts.googleapis.com/css?family=Montserrat', false, '1.0', 'all' );
    It’s located off-site, so you need to give the full URL. It also has no dependencies, is at
    version 1.0, and should be loaded on all media.

    View Slide

  88. wp_enqueue_scripts (for JS)
    wp_enqueue_scripts (for JS)
    The same function can be used to register and enqueue scripts, if your theme has any.
    To register and then enqueue a file called global.js in your theme, for example, you would
    add this below your wp_enqueue_style() lines:
    wp_register_script( 'global', get_template_directory_uri() . '/js/global.js', array('jquery'), '1.0', true );
    wp_enqueue_script('global');

    View Slide

  89. wp_register_script()
    wp_register_script()
    wp_register_script( 'global', get_template_directory_uri() . '/js/global.js', array('jquery'), '1.0', true );
    The first line registers a file called global.js, which is in a folder called “js” in the theme
    folder. It depends on jQuery to function (so it should load after jQuery does), it’s at version
    1.0, and it should appear just before the closing

    View Slide

  90. Conditionally enqueuing
    Conditionally enqueuing
    WordPress comes with lots of .js files ready to go (they’ve already been registered), but
    until you enqueue them they won’t be loaded in your theme files.
    comment-reply.js is one of these pre-registered scripts. It enhances threaded comments
    on single posts, but you only want it to load when it’s useful. To limit when this file is
    included, add this conditional statement to the end of your my_scripts_and_styles()
    function:
    if ( is_singular() && get_option( 'thread_comments' ) && comments_open() ) {
    wp_enqueue_script( 'comment-reply' );
    }
    Reference: http://codex.wordpress.org/Function_Reference/wp_enqueue_script#Default_Scripts_Included_and_Registered_by_WordPress

    View Slide

  91. wp_enqueue_scripts in full
    wp_enqueue_scripts in full
    Here is the full block of code for your functions.php file:
    // Register and enqueue styles and scripts
    function my_scripts_and_styles() {
    wp_register_style( 'core', get_stylesheet_uri(), false, '1.0', 'all' );
    wp_register_style( 'fonts', 'http://fonts.googleapis.com/css?family=Montserrat', false, '1.0', 'all' );
    wp_enqueue_style( 'core' );
    wp_enqueue_style( 'fonts' );
    // Only include the two lines below if you actually have global.js:
    wp_register_script( 'global', get_template_directory_uri() . '/js/global.js', array('jquery'), '1.0', true );
    wp_enqueue_script('global');
    if ( is_singular() && get_option( 'thread_comments' ) && comments_open() ) {
    wp_enqueue_script( 'comment-reply' );
    }
    }
    add_action( 'wp_enqueue_scripts', 'my_scripts_and_styles' );

    View Slide

  92. excerpt_more
    excerpt_more
    By default, WordPress adds [...] to the end of the_excerpt(). To replace this with an
    ellipsis character and a “Continue reading “[post title]” →” link to the full post, include this
    code in functions.php:
    // Append ellipsis and continue reading link to automatic excerpts
    function my_excerpt_more( $more ) {
    return ' … Continue reading “'. get_the_title() .'” →';
    }
    add_filter('excerpt_more', 'my_excerpt_more');

    View Slide

  93. excerpt_more() in action
    excerpt_more() in action
    This:
    now looks like this:

    View Slide

  94. add_image_size()
    add_image_size()
    If you want WordPress to automatically generate more image sizes than the ones available
    under Settings → Media, you can do so with this code:
    // Register custom image sizes
    add_image_size( 'slider', 750, 300, true ); // cropped to exactly 750 pixels wide by 300 pixels tall
    add_image_size( 'narrow', 150, 999, false ); // sized to 150 pixels wide and proportional height (max 999 pixels)
    If you’ve uploaded images to your media library before adding this code, you need to run a
    plugin like Regenerate Thumbnails ( ). All
    future uploads will create these custom image sizes automatically.
    wordpress.org/plugins/regenerate-thumbnails/
    Reference: codex.wordpress.org/Function_Reference/add_image_size

    View Slide

  95. image_size_names_choose
    image_size_names_choose
    This code will make your new image sizes available when inserting a picture into a post or
    a page:
    // Add custom sizes to the WordPress Media Library
    function my_custom_sizes( $sizes ) {
    return array_merge( $sizes, array(
    'slider' => __( 'Image Slider' ),
    'narrow' => __( 'Narrow' )
    ) );
    }
    add_filter( 'image_size_names_choose', 'my_custom_sizes' );
    Make sure the lowercase name above matches whatever you called your new image sizes
    in the previous step.
    Reference: codex.wordpress.org/Plugin_API/Filter_Reference/image_size_names_choose

    View Slide

  96. Remove inline [gallery] styles
    Remove inline [gallery] styles
    The default WordPress gallery inserts some inline CSS that you may want to override in
    your theme. You could use lots of !importants in your stylesheet, but it’s super easy to
    just stop them from loading entirely:
    // Remove inline WordPress gallery styles
    add_filter( 'use_default_gallery_style', '__return_false' );

    View Slide

  97. add_theme_support( 'post-thumbnails' )
    add_theme_support( 'post-thumbnails' )
    Enable featured images for posts and pages with this:
    // Add support for featured images
    add_theme_support( 'post-thumbnails' );
    Then in index.php, check for and display the featured image. This code will get the
    “thumbnail” size, and add the class “alignright”:
    if ( has_post_thumbnail() ) {
    the_post_thumbnail( 'thumbnail', array( 'class' => 'alignright' ) );
    }
    References:
    codex.wordpress.org/Post_Thumbnails
    codex.wordpress.org/Function_Reference/the_post_thumbnail

    View Slide

  98. List of requested features, revisited
    List of requested features, revisited
    Responsive design ✓

    View Slide

  99. List of requested features, revisited
    List of requested features, revisited
    Responsive design ✓
    Homepage with intro paragraph and latest post ✓

    View Slide

  100. List of requested features, revisited
    List of requested features, revisited
    Responsive design ✓
    Homepage with intro paragraph and latest post ✓
    About page with image gallery ✓

    View Slide

  101. List of requested features, revisited
    List of requested features, revisited
    Responsive design ✓
    Homepage with intro paragraph and latest post ✓
    About page with image gallery ✓
    Blog with widgets in the sidebar ✓

    View Slide

  102. Questions?
    Questions?
    @LinnOyenFarley
    @LinnOyenFarley
    [email protected]
    [email protected]
    Slides, HTML & CSS template, and finished theme
    drollic.ca/wcto14

    View Slide