Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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”

Slide 5

Slide 5 text

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/

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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.

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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!

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

No content

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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 {}

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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.

Slide 23

Slide 23 text

Interlude: Interlude: Intro to PHP Intro to PHP

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

wp_title() in action wp_title() in action Replacing this: Feline Design Co. with this: <?php wp_title(); ?> outputs this (when viewing the blog post with this title): » Blog post #1

Slide 35

Slide 35 text

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: <?php wp_title('—', true, 'right'); bloginfo( 'name' ); ?> 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

Slide 36

Slide 36 text

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: References: codex.wordpress.org/Function_Reference/wp_head codex.wordpress.org/Function_Reference/wp_footer

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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').

Slide 39

Slide 39 text

bloginfo('template_directory') in action bloginfo('template_directory') in action Replacing this: Feline Design Co. with this: <?php bloginfo('name'); ?> outputs this: Feline Design Co.

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

wp_nav_menu() in action wp_nav_menu() in action ...outputs something like this: Until you assign a menu to the “main-nav” theme location, wp_nav_menu() will default to an alphabetical list of your pages.

Slide 43

Slide 43 text

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.

Slide 44

Slide 44 text

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.

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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

Not Found

Sorry, nothing found.

Slide 47

Slide 47 text

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.

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

Recap: the full loop Recap: the full loop Here is the loop in its entirety, with comments throughout:

Not Found

Sorry, nothing found.

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

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.

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

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:

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

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: Reference: codex.wordpress.org/Function_Reference/is_front_page

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

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 ?>

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

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

Slide 62

Slide 62 text

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 outputs this: Reference: codex.wordpress.org/Template_Tags/the_time

Slide 63

Slide 63 text

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

Slide 64

Slide 64 text

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

And this is how it looks:

Slide 65

Slide 65 text

Homepage: complete! Homepage: complete!

Slide 66

Slide 66 text

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:

Reference: codex.wordpress.org/Function_Reference/is_page

Slide 67

Slide 67 text

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: Reference: codex.wordpress.org/Function_Reference/comments_template

Slide 68

Slide 68 text

comments_template() in action comments_template() in action

Slide 69

Slide 69 text

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

Slide 70

Slide 70 text

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:

Slide 71

Slide 71 text

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:

Slide 72

Slide 72 text

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

Slide 73

Slide 73 text

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:

Slide 74

Slide 74 text

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: ?>

Reference: codex.wordpress.org/Function_Reference/is_single

Slide 75

Slide 75 text

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

Slide 76

Slide 76 text

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.

Slide 77

Slide 77 text

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

Slide 78

Slide 78 text

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

Slide 79

Slide 79 text

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'); ?>

Slide 80

Slide 80 text

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.)

Slide 81

Slide 81 text

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' );

Slide 82

Slide 82 text

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:

Slide 83

Slide 83 text

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' );

Slide 84

Slide 84 text

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.)

Slide 85

Slide 85 text

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

Slide 86

Slide 86 text

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/

Slide 87

Slide 87 text

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.

Slide 88

Slide 88 text

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');

Slide 89

Slide 89 text

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 tag instead of in the . References: (writes the code for you) codex.wordpress.org/Function_Reference/wp_register_script generatewp.com/register_script/

Slide 90

Slide 90 text

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

Slide 91

Slide 91 text

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' );

Slide 92

Slide 92 text

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');

Slide 93

Slide 93 text

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

Slide 94

Slide 94 text

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

Slide 95

Slide 95 text

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

Slide 96

Slide 96 text

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' );

Slide 97

Slide 97 text

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

Slide 98

Slide 98 text

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

Slide 99

Slide 99 text

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

Slide 100

Slide 100 text

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

Slide 101

Slide 101 text

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 ✓

Slide 102

Slide 102 text

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