# Credits Source: https://developer.wordpress.org/themes/credits/ - @ancawonka - @Anthonynotes - @atachibana - @austingunter - @bandonrandon - @utz119 - @BFTrick - @BigActual - @bkozma - @boborchard - @Brainfestation - @celloexpressions - @charliehanger - @claymonk - @code\_poet - @colorful-tones - @crondeau - @davidjlaietta - @daisyo - @digisavvy - @DrewAPicture - @enricchi - @esmi - @fabianapsimoes - @fiveo - @grapplerulrich - @greenshady - @hanni - @hlashbrooke - @hardeepasrani - @iandstewart - @jackreichert - @jacobmc - @JasonM4563 - @jazzs3quence - @jboydston - @jcastaneda - @jcrglobalcaplaw - @JenniferBourn - @jerrysarcastic - @jgclarke - @jhoffm34 - @jim-spencer - @jimdoran - @juhise - @juliekuehl - @kadamwhite - @kafleg - @karmatosed - @kenshino - @kenyasullivan - @kpdesign - @lettergrade - @linux-garage - @lizkaraffa - @lorax - @mariawoothemescom - @markel - @martydia - @missybunnie - @mt\_Suzette - @nao - @NikV - @Otto42 - @ozzyr - @philiparthurmoore - @poena - @PriscillaBiju - @rachelbaker - @Raporteur - @rahulsprajapati - @rclations - @rhauptman - @RussE - @ryanr14 - @SagarGurnani - @samuelsidler - @sarahovenall - @semblance\_er - @sewmyheadon - @SeReedMedia - @sheebaabraham - @siobhan - @stubbs123 - @suastex - @sushil-adhikari - @Techdoode - @thepixelista - @topher1kenobe - @TJNowell - @xfrontend - @viniciuslourenco - @vrm --- # Page Templates Source: https://developer.wordpress.org/themes/template-files-section/page-template-files/ Page templates are a specific type of [template file](https://developer.wordpress.org/themes/basics/template-files/ "Template Files") that can be applied to a specific page or groups of pages. As of WordPress 4.7 page templates support all post types. For more details how to set a page template to specific post types [see example below](#creating-page-templates-for-specific-post-types). Since a page template is a specific type of template file, here are some distinguishing features of page templates: - Page templates are used to change the look and feel of a page. - A page template can be applied to a single page, a page section, or a class of pages. - Page templates generally have a high level of specificity, targeting an individual page or group of pages. For example, a page template named `page-about.php` is more specific than the template files `page.php` or `index.php` as it will only affect a page with the slug of “about.” - If a page template has a template name, WordPress users editing the page have control over what template will be used to render the page. ## Uses for Page Templates Page templates display your site’s dynamic content on a page, e.g., posts, news updates, calendar events, media files, etc. You may decide that you want your homepage to look a specific way, that is quite different to other parts of your site. Or, you may want to display a featured image that links to a post on one part of the page, have a list of latest posts elsewhere, and use a custom navigation. You can use page templates to achieve these things. This section shows you how to build page templates that can be selected by your users through their admin screens. For example, you can build page templates for: - full-width, one-column - two-column with a sidebar on the right - two-column with a sidebar on the left - three-column ## Page Templates within the Template Hierarchy When a person browses to your website, WordPress selects which template to use for rendering that page. As we learned earlier in the [Template Hierarchy](https://developer.wordpress.org/themes/basics/template-hierarchy/ "Template Hierarchy"), WordPress looks for template files in the following order: 1. **Page Template —** If the page has a custom template assigned, WordPress looks for that file and, if found, uses it. 2. **`page-{slug}.php` —** If no custom template has been assigned, WordPress looks for and uses a specialized template that contains the page’s slug. 3. **`page-{id}.php` —** If a specialized template that includes the page’s slug is not found, WordPress looks for and uses a specialized template named with the page’s ID. 4. **`page.php` —** If a specialized template that includes the page’s ID is not found, WordPress looks for and uses the theme’s default page template. 5. **`singular.php` —** If `page.php` is not found, WordPress looks for and uses the theme’s template used for a single post, irregardless of post type. 6. **`index.php` —** If no specific page templates are assigned or found, WordPress defaults back to using the theme’s index file to render pages. There is also a WordPress-defined template named `paged.php`. It is *not* used for the page post-type but rather for displaying multiple pages of archives. ## Page Templates Purpose & User Control If you plan on making a custom page template for your theme, you should decide a couple of things before proceeding: - Whether the page template will be for one specific page or for any page; and - What type of user control you want available for the template. Every page template that has a template name can be selected by a user when they create or edit a page. The list of available templates can be found at **Pages > Add New > Attributes > Template**. Therefore, a WordPress user can choose any page template with a template name, which might not be your intention. For example, if you want to have a specific template for your “About” page, it might not be appropriate to name that page template “About Template” as it would be globally available to all pages (i.e. the user could apply it to any page). Instead, [create a single use template](https://developer.wordpress.org/themes/template-files-section/page-template-files/#creating-a-custom-page-template-for-one-specific-page) and WordPress will render the page with the appropriate template, whenever a user visits the “About” page. Conversely, many themes include the ability to choose how many columns a page will have. Each of these options is a page template that is available globally. To give your WordPress users this global option, you will need to create page templates for each option and give each a template name. Dictating whether a template is for global use vs. singular use is achieved by the way the file is named and whether or not is has a specific comment. Sometimes it is appropriate to have a template globally available even if it appears to be a single use case. When you’re creating themes for release, it can be hard to predict what a user will name their pages. Portfolio pages are a great example as not every WordPress user will name their portfolio the same thing or have the same page ID and yet they may want to use that template. ## File Organization of Page Templates As discussed in [Organizing Theme Files](https://developer.wordpress.org/themes/basics/organizing-theme-files/), WordPress recognizes the subfolder **page-templates**. Therefore, it’s a good idea to store your global page templates in this folder to help keep them organized. A specialized page template file (those created for only one time use) **cannot** be in a sub-folder, nor, if using a [Child Theme](https://developer.wordpress.org/themes/advanced-topics/child-themes/#how-to-create-a-child-theme), in the Parent Theme’s folder. ## Creating Custom Page Templates for Global Use Sometimes you’ll want a template that can be used globally by any page, or by multiple pages. Some developers will group their templates with a filename prefix, such as `page_two-columns.php` ***Important!*** Do not use `page-` as a prefix, as WordPress will interpret the file as a specialized template, meant to apply to only *one* page on your site. For information on theme file-naming conventions and filenames you cannot use, see [reserved theme filenames](https://developer.wordpress.org/themes/basics/template-files/#common-wordpress-template-files "Theme Development"). A quick, safe method for creating a new page template is to make a copy of `page.php` and give the new file a distinct filename. That way, you start off with the HTML structure of your other pages and you can edit the new file as needed. To create a global template, write an opening PHP comment at the top of the file that states the template’s name. ```php ``` It’s a good idea to choose a name that describes what the template does as the name is visible to WordPress users when they are editing the page. For example, you could name your template Homepage, Blog, or Portfolio. This example from the TwentyFourteen theme creates a page template called Full Width Page: ```php body_class()` function, WordPress will print classes in the `body` tag for the post type class name (`page`), the page’s ID (`page-id-{ID}`), and the page template used. For the default `page.php`, the class name generated is `page-template-default`: ```markup ``` A specialized template (`page-{slug}.php` or `page-{ID}.php`) also gets the `page-template-default` class rather than its own body class. When using a custom page template, the class `page-template` will print, along with a class naming the specific template. For example, if your custom page template file is named as follows: ```php ``` Then then rendered HTML generated will be as follows: ```markup ``` Notice the `page-template-my-custom-page-php` class that is applied to the `body` tag. ## Page Template Functions These built-in WordPress functions and methods can help you work with page templates: - `get_page_template()` returns the path of the page template used to render the page. - `wp_get_theme()->get_page_templates()` returns all custom page templates available to the currently active theme (`get_page_templates()` is a method of the `WP_Theme` class). - `is_page_template()` returns true or false depending on whether a custom page template was used to render the page. - `get_page_template_slug()` returns the value of custom field `_wp_page_template` (`null` when the value is empty or “default”).If a page has been assigned a custom template, the filename of that template is stored as the value of a [custom field](https://codex.wordpress.org/Custom_Fields "Custom Fields") named `'_wp_page_template'` (in the [`wp_postmeta`](https://codex.wordpress.org/Database_Description#Table:_wp_postmeta "Database Description") database table). (Custom fields starting with an underscore do not display in the edit screen’s custom fields module.) --- # Template Hierarchy Source: https://developer.wordpress.org/themes/basics/template-hierarchy/ As discussed, [template files](https://developer.wordpress.org/themes/basics/template-files/ "Template files page") are modular, reusable files, used to generate the web pages on your WordPress site. Some template files (such as the header and footer template) are used on all of your site’s pages, while others are used only under specific conditions. This article explains **how WordPress determines which template file(s) to use on individual pages**. If you want to customize an existing WordPress theme it will help you decide which template file needs to be edited. You can also use [Conditional Tags](https://developer.wordpress.org/themes/basics/conditional-tags/ "Conditional Tags") to control which templates are loaded on a specific page. ## The Template File Hierarchy ### Overview WordPress uses the [query string](https://wordpress.org/support/article/glossary/#query-string) to decide which template or set of templates should be used to display the page. The query string is information that is contained in the link to each part of your website. Put simply, WordPress searches down through the template hierarchy until it finds a matching template file. To determine which template file to use, WordPress: 1. Matches every query string to a query type to decide which page is being requested (for example, a search page, a category page, etc); 2. Selects the template in the order determined by the template hierarchy; 3. Looks for template files with specific names in the current theme’s directory and uses the **first matching template file** as specified by the hierarchy. With the exception of the basic `index.php` template file, you can choose whether you want to implement a particular template file or not. In these examples, the PHP file extension is used. In block themes, HTML files are used instead, but the template hierarchy is the same. If WordPress cannot find a template file with a matching name, it will skip to the next file in the hierarchy. If WordPress cannot find any matching template file, the theme’s `index.php` file will be used. When you are using a [child theme](https://developer.wordpress.org/themes/advanced-topics/child-themes/), any file you add to your child theme will over-ride the same file in the parent theme. For example, both themes contain the same template `category.php`, then child theme’s template is used. If a child theme contains the specific template such as `category-unicorns.php` and the parent theme contains lower prioritized template such as `category.php`, then child theme’s `category-unicorns.php` is used. Contrary, if a child theme contains general template only such as `category.php` and the parent theme contains the specific one such as `category-unicorns.php`, then parent’s template `category-unicorns.php` is used. ### Examples If your blog is at `http://example.com/blog/` and a visitor clicks on a link to a category page such as `http://example.com/blog/category/your-cat/`, WordPress looks for a template file in the current theme’s directory that matches the category’s ID to generate the correct page. More specifically, WordPress follows this procedure: 1. Looks for a template file in the current theme’s directory that matches the category’s slug. If the category slug is “unicorns,” then WordPress looks for a template file named `category-unicorns.php`. 2. If `category-unicorns.php` is missing and the category’s ID is 4, WordPress looks for a template file named `category-4.php`. 3. If `category-4.php` is missing, WordPress will look for a generic category template file, `category.php`. 4. If `category.php` does not exist, WordPress will look for a generic archive template, `archive.php`. 5. If `archive.php` is also missing, WordPress will fall back to the main theme template file, `index.php`. ### Visual Overview The following diagram shows which template files are called to generate a WordPress page based on the WordPress template hierarchy. [![](https://i0.wp.com/developer.wordpress.org/files/2014/10/Screenshot-2019-01-23-00.20.04.png?resize=1024%2C639&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2014/10/Screenshot-2019-01-23-00.20.04.png?ssl=1)## The Template Hierarchy In Detail While the template hierarchy is easier to understand as a diagram, the following sections describe the order in which template files are called by WordPress for a number of query types. ### Home Page display By default, WordPress sets your site’s home page to display your latest blog posts. This page is called the blog posts index. You can also set your blog posts to display on a separate static page. The template file `home.php` is used to render the blog posts index, whether it is being used as the front page or on separate static page. If `home.php` does not exist, WordPress will use `index.php`. 1. `home.php` 2. `index.php` If `front-page.php` exists, it will override the `home.php` template. ### Front Page display The `front-page.php` template file is used to render your site’s front page, whether the front page displays the blog posts index (mentioned above) or a static page. The front page template takes precedence over the blog posts index (`home.php`) template. If the `front-page.php` file does not exist, WordPress will either use the `home.php` or `page.php` files depending on the setup in Settings → Reading. If neither of those files exist, it will use the `index.php` file. 1. `front-page.php` – Used for both “**your latest posts**” or “**a static page**” as set in the **front page displays** section of Settings → Reading. 2. `home.php` – If WordPress cannot find `front-page.php` and “**your latest posts**” is set in the **front page displays** section, it will look for `home.php`. Additionally, WordPress will look for this file when the **posts page** is set in the **front page displays** section. 3. `page.php` – When “**front page**” is set in the **front page displays** section. 4. `index.php` – When “**your latest posts**” is set in the **front page displays** section but `home.php` does not exist *or* when **front page** is set but `page.php` does not exist. As you can see, there are a lot of rules to what path WordPress takes. Using the chart above is the best way to determine what WordPress will display. ### Privacy Policy Page display The `privacy-policy.php` template file is used to render your site’s Privacy Policy page. The Privacy Policy page template takes precedence over the static page (`page.php`) template. If the `privacy-policy.php` file does not exist, WordPress will either use the `page.php` or `singular.php` files depending on the available templates. If neither of those files exist, it will use the `index.php` file. 1. `privacy-policy.php` – Used for the Privacy Policy page set in the **Change your Privacy Policy page** section of Settings → Privacy. 2. `custom template file` – The [page template](https://developer.wordpress.org/themes/template-files-section/page-template-files/) assigned to the page. See `get_page_templates()`. 3. `page-{slug}.php` – If the page slug is `privacy`, WordPress will look to use `page-privacy.php`. 4. `page-{id}.php` – If the page ID is 6, WordPress will look to use `page-6.php`. 5. `page.php` 6. `singular.php` 7. `index.php` ### Single Post The single post template file is used to render a single post. WordPress uses the following path: 1. `single-{post-type}-{slug}.php` – (Since 4.4) First, WordPress looks for a template for the specific post. For example, if [post type](https://developer.wordpress.org/themes/basics/post-types/) is `product` and the post slug is `dmc-12`, WordPress would look for `single-product-dmc-12.php`. 2. `single-{post-type}.php` – If the post type is `product`, WordPress would look for `single-product.php`. 3. `single.php` – WordPress then falls back to `single.php`. 4. `singular.php` – Then it falls back to `singular.php`. 5. `index.php` – Finally, as mentioned above, WordPress ultimately falls back to `index.php`. ### Single Page The template file used to render a static page (`page` post-type). Note that unlike other post-types, `page` is special to WordPress and uses the following path: 1. `custom template file` – The [page template](https://developer.wordpress.org/themes/template-files-section/page-template-files/) assigned to the page. See `get_page_templates()`. 2. `page-{slug}.php` – If the page slug is `recent-news`, WordPress will look to use `page-recent-news.php`. 3. `page-{id}.php` – If the page ID is 6, WordPress will look to use `page-6.php`. 4. `page.php` 5. `singular.php` 6. `index.php` ### Category Rendering category archive index pages uses the following path in WordPress: 1. `category-{slug}.php` – If the category’s slug is `news`, WordPress will look for `category-news.php`. 2. `category-{id}.php` – If the category’s ID is `6`, WordPress will look for `category-6.php`. 3. `category.php` 4. `archive.php` 5. `index.php` ### Tag To display a tag archive index page, WordPress uses the following path: 1. `tag-{slug}.php` – If the tag’s slug is `sometag`, WordPress will look for `tag-sometag.php`. 2. `tag-{id}.php` – If the tag’s ID is `6`, WordPress will look for `tag-6.php`. 3. `tag.php` 4. `archive.php` 5. `index.php` ### Custom Taxonomies [Custom taxonomies](https://developer.wordpress.org/themes/basics/categories-tags-custom-taxonomies/) use a slightly different template file path: 1. `taxonomy-{taxonomy}-{term}.php` – If the taxonomy is `sometax`, and taxonomy’s term is `someterm`, WordPress will look for `taxonomy-sometax-someterm.php.` In the case of [post formats](https://developer.wordpress.org/themes/functionality/post-formats/), the taxonomy is ‘post\_format’ and the terms are ‘post-format-{format}. i.e. `taxonomy-post_format-post-format-link.php` for the link post format. 2. `taxonomy-{taxonomy}.php` – If the taxonomy were `sometax`, WordPress would look for `taxonomy-sometax.php`. 3. `taxonomy.php` 4. `archive.php` 5. `index.php` ### Custom Post Types [Custom Post Types](https://developer.wordpress.org/themes/basics/post-types/) use the following path to render the appropriate archive index page. 1. `archive-{post_type}.php` – If the post type is `product`, WordPress will look for `archive-product.php`. 2. `archive.php` 3. `index.php` (For rendering a single post type template, refer to the [single post display](#single-post "Single Post Display") section above.) ### Author display Based on the above examples, rendering author archive index pages is fairly explanatory: 1. `author-{nicename}.php` – If the author’s nice name is `matt`, WordPress will look for `author-matt.php`. 2. `author-{id}.php` – If the author’s ID were `6`, WordPress will look for `author-6.php`. 3. `author.php` 4. `archive.php` 5. `index.php` ### Date Date-based archive index pages are rendered as you would expect: 1. `date.php` 2. `archive.php` 3. `index.php` ### Search Result Search results follow the same pattern as other template types: 1. `search.php` 2. `index.php` ### 404 (Not Found) Likewise, 404 template files are called in this order: 1. `404.php` 2. `index.php` ### Attachment Rendering an attachment page (`attachment` post-type) uses the following path: 1. `{MIME-type}.php` – can be any [MIME type](http://en.wikipedia.org/wiki/Internet_media_type "http://en.wikipedia.org/wiki/Internet_media_type") (For example: `image.php`, `video.php`, `pdf.php`). For `text/plain`, the following path is used (in order): 1. `text-plain.php` 2. `plain.php` 3. `text.php` 2. `attachment.php` 3. `single-attachment-{slug}.php` – For example, if the attachment slug is `holiday`, WordPress would look for `single-attachment-holiday.php`. 4. `single-attachment.php` 5. `single.php` 6. `singular.php` 7. `index.php` As of WordPress 6.4, attachment pages are [no longer enabled by default](https://make.wordpress.org/core/2023/10/16/changes-to-attachment-pages/) on new installations. Users can enable them with a plugin, so it is still good practice to test your theme and ensure it properly displays content when viewing an attachment page. ### Embeds The embed template file is used to render a post which is being embedded. Since 4.5, WordPress uses the following path: 1. `embed-{post-type}-{post_format}.php` – First, WordPress looks for a template for the specific post. For example, if its post type is `post` and it has the audio format, WordPress would look for `embed-post-audio.php`. 2. `embed-{post-type}.php` – If the post type is `product`, WordPress would look for `embed-product.php`. 3. `embed.php` – WordPress then falls back to embed`.php`. 4. Finally, WordPress ultimately falls back to its own `wp-includes/theme-compat/embed.php` template. ## Non-ASCII Character Handling Since WordPress 4.7, any dynamic part of a template name which includes non-ASCII characters in its name actually supports both the un-encoded and the encoded form, in that order. You can choose which to use. Here’s the page template hierarchy for a page named “Hello World 😀” with an ID of `6`: - `page-hello-world-😀.php` - `page-hello-world-%f0%9f%98%80.php` - `page-6.php` - `page.php` - `singular.php` The same behaviour applies to post slugs, term names, and author nicenames. ## Filter Hierarchy The WordPress template system lets you filter the hierarchy. This means that you can insert and change things at specific points of the hierarchy. The filter (located in the [`get_query_template()`](https://developer.wordpress.org/reference/functions/get_query_template/) function) uses this filter name: `"{$type}_template"` where `$type` is the template type. Here is a list of all available filters in the template hierarchy: - `embed_template` - `404_template` - `search_template` - `frontpage_template` - `home_template` - `privacypolicy_template` - `taxonomy_template` - `attachment_template` - `single_template` - `page_template` - `singular_template` - `category_template` - `tag_template` - `author_template` - `date_template` - `archive_template` - `index_template` ### Example For example, let’s take the default author hierarchy: - `author-{nicename}.php` - `author-{id}.php` - `author.php` To add `author-{role}.php` before `author.php`, we can manipulate the actual hierarchy using the ‘author\_template’ template type. This allows a request for /author/username where username has the role of editor to display using author-editor.php if present in the current themes directory. ```php function author_role_template( $templates = '' ) { $author = get_queried_object(); $role = $author->roles[0]; if ( ! is_array( $templates ) && ! empty( $templates ) ) { $templates = locate_template( array( "author-$role.php", $templates ), false ); } elseif ( empty( $templates ) ) { $templates = locate_template( "author-$role.php", false ); } else { $new_template = locate_template( array( "author-$role.php" ) ); if ( ! empty( $new_template ) ) { array_unshift( $templates, $new_template ); } } return $templates; } add_filter( 'author_template', 'author_role_template' ); ``` Changelog: - **Updated** 2022-02-15. Added a notice explaining that the template hierarchy is the same for classic and block themes, but that the examples uses .php files and block themes use .html files. --- # Template Tags Source: https://developer.wordpress.org/themes/basics/template-tags/ Template tags are used within themes to **retrieve content from your database**. The content could be anything from a blog title to a complete sidebar. Template tags are the preferred method to pull content into your theme because: - they can print dynamic content; - they can be used in multiple theme files; and - they separate the theme into smaller, more understandable, sections. ## What is a Template Tag? A template tag is simply a piece of code that tells WordPress to get something from the database. It is broken up into three components: - A PHP code tag - A WordPress function - Optional parameters You can use a template tag to call another theme file or some information from the database. For example, the template tag `get_header()` tells WordPress to get the `header.php` file and include it in the current theme file. Similarly, `get_footer()` tells WordPress to get the footer.php file. There are also other kinds of template tags: - `the_title()` – tells WordPress to get the title of the page or post from the database and include it. - `bloginfo( 'name' )` – tells WordPress to get the blog title out of the database and include it in the template file. If you look closely at the last example, you will also see that there is a parameter between the parenthesis. Parameters let you do two things: 1. ask for specific pieces of information and 2. format the information in a certain way. [Parameters are covered extensively below](#parameters), but it’s useful to be aware that you can send WordPress-specific instructions for how you want the data presented. ## Why Use Template Tags By encapsulating all of the code for a particular chunk of content, template tags make it very easy to include various pieces of a template in a theme file and also to maintain the theme. It is far easier to create one `header.php` file and have all of your theme templates like `single.php`, `page.php`, `front-page.php`, etc. reference that one theme file using `get_header()` than copying and pasting the code into each theme file. It also makes maintenance easier. Whenever you make a change in your `header.php` file, the change is automatically carried over into all of your other theme files. Another reason to use template tags is to display dynamic data, i.e. data from the database. In your header, you could manually include the `title` tag, like so: ```xml My Personal Website ``` However, doing this means manually editing your theme any time you want to change the title of your website. Instead, it’s easier to include the `bloginfo( 'name' )` template tag, which automatically fetch the site title from the database. Now, you can change the title of your site in WordPress, rather than having to hard code your theme templates. ## How to Use Template Tags Using template tags is very simple. In any template file you can use a template tag by simply printing one line of php code to call the template tag. Printing the header.php file is as simple as: ```php get_header(); ``` ### Parameters Some template tags let you pass parameters. Parameters are extra pieces of information that determine what is retrieved from the database. For example, the `bloginfo()` template tag allows you to give it a parameter telling WordPress the specific piece of information you want. To print the blog name, you just pass along the parameter “name,” like so: ```php bloginfo( 'name' ); ``` To print the version of WordPress that the blog is running on, you would pass a parameter of “version”: ```php bloginfo( 'version' ); ``` For each template tag, the parameters differ. A list of the parameters and what they can do can be found on specific template tag pages located throughout the [code reference](https://developer.wordpress.org/reference/). ### Using Template Tags Within the Loop Many template tags work within the [WordPress Loop](https://developer.wordpress.org/themes/basics/the-loop/). This means that they are included in the template files as part of the php “loop” that generates the pages users see based upon the instructions inside of the loop. The WordPress loop begins with: ```php if ( have_posts() ) : while ( have_posts() ) : the_post(); ``` Template tags that work within the loop must be in the middle area, before the ending section of the loop below: ```php endwhile; else : _e( 'Sorry, no posts matched your criteria.', 'devhub' ); endif; ``` Some of template tags that need to be inside of the loop include - [the\_content()](https://developer.wordpress.org/reference/functions/the_content/) - [the\_excerpt()](https://developer.wordpress.org/reference/functions/the_excerpt/) - [next\_post()](https://developer.wordpress.org/reference/functions/next_post/) - [previous\_post()](https://developer.wordpress.org/reference/functions/previous_post/) The main reason why some functions require the loop is because they require the global post object to be set. If the template tag you want to use doesn’t have to be within the loop - [wp\_list\_cats()](https://developer.wordpress.org/reference/functions/wp_list_cats/) - [wp\_list\_pages()](https://developer.wordpress.org/reference/functions/wp_list_pages/) then you can put it in any file you’d like, for instance in the sidebar, header, or footer template files. These are functions that typically do not require the global post object. ## See Also - [Conditional Tags](https://developer.wordpress.org/themes/basics/conditional-tags/) - [Complete list of Template Tags](https://developer.wordpress.org/themes/references/list-of-template-tags/) - [Plugin API Hooks](_wp_link_placeholder) --- # The Loop Source: https://developer.wordpress.org/themes/basics/the-loop/ The Loop is the default mechanism WordPress uses for outputting posts through a theme’s [template files](https://developer.wordpress.org/themes/basics/template-files/). How many posts are retrieved is determined by the number of posts to show per page defined in the Reading settings. Within the Loop, WordPress retrieves each post to be displayed on the current page and formats it according to your theme’s instructions. The Loop extracts the data for each post from the WordPress database and inserts the appropriate information in place of each [template tag](https://developer.wordpress.org/themes/basics/template-tags/). Any HTML or PHP code in The Loop will be processed **for each post**. To put it simply, the Loop is true to its name: it loops through each post retrieved for the current page one at a time and performs the action specified in your theme. You can use the Loop for a number of different things, for example to: - display post titles and excerpts on your blog’s homepage; - display the content and comments on a single post; - display the content on an individual page using template tags; and - display data from [Custom Post Types](https://developer.wordpress.org/themes/functionality/pages-posts-custom-post-types/) and Custom Fields. You can customize the Loop across your template files to display and manipulate different content. ## The Loop in Detail The basic loop is: ```php ``` This loop says that when there are posts, loop through and display the posts. Broken down into more detail: - The `have_posts()` function checks whether there are any posts. - If there are posts, a **`while`** loop continues to execute as long as the condition in the parenthesis is logically true. As long as `have_posts()` continues to be true, the loop will continue. ### Using The Loop The Loop should be placed in `index.php`, and in any other templates which are used to display post information. Because you do not want to duplicate your header over and over, the loop should always be placed after the call to `get_header()`. For example: ```php ``` In the above example, the end of the Loop is shown with an `endwhile` and `endif`. The Loop must always begin with the same `if` and `while` statements, as mentioned above and must end with the same end statements. Any [template tags](https://developer.wordpress.org/themes/basics/template-tags/) that you wish to apply to all posts must exist between the beginning and ending statements. You can include a custom 404 “not found” message that will be displayed if no posts matching the specified criteria are available. The message must be placed between the `endwhile` and `endif` statements, as seen in examples below. An extremely simple `index.php` file would look like: ```php ``` ## What the Loop Can Display The Loop can display a number of different elements for each post. For example, some common [template tags](https://developer.wordpress.org/themes/basics/template-tags/ "Template Tags") used in many themes are: - `next_post_link()` – a link to the post published chronologically *after* the current post - `previous_post_link()` – a link to the post published chronologically *before* the current post - `the_category()` – the category or categories associated with the post or page being viewed - `the_author()` – the author of the post or page - `the_content()` – the main content for a post or page - `the_excerpt()` – the first 55 words of a post’s main content followed by an ellipsis (…) or read more link that goes to the full post. You may also use the “Excerpt” field of a post to customize the length of a particular excerpt. - `the_ID()` – the ID for the post or page - `the_meta()` – the custom fields associated with the post or page - `the_shortlink()` – a link to the page or post using the url of the site and the ID of the post or page - `the_tags()` – the tag or tags associated with the post - `the_title()` – the title of the post or page - `the_time()` – the time or date for the post or page. This can be customized using standard php date function formatting. You can also use [conditional tags](https://developer.wordpress.org/themes/basics/conditional-tags/), such as: - `is_home()` – Returns true if the current page is the homepage - `is_admin()` – Returns true if inside Administration Screen, false otherwise - `is_single()` – Returns true if the page is currently displaying a single post - `is_page()` – Returns true if the page is currently displaying a single page - `is_page_template()` – Can be used to determine if a page is using a specific template, for example: `is_page_template('about-page.php')` - `is_category()` – Returns true if page or post has the specified category, for example: `is_category('news')` - `is_tag()` – Returns true if a page or post has the specified tag - `is_author()` – Returns true if inside author’s archive page - `is_search()` – Returns true if the current page is a search results page - `is_404()` – Returns true if the current page does not exist - `has_excerpt()` – Returns true if the post or page has an excerpt ## Examples Let’s take a look at some examples of the Loop in action: ### Basic Examples #### Blog Archive Most blogs have a blog archive page, which can show a number of things including the post title, thumbnail, and excerpt. The example below shows a simple loop that checks to see if there are any posts and, if there are, outputs each post’s title, thumbnail, and excerpt. If no posts exists, it displays the message in parentheses. ```php ', '' ); the_post_thumbnail(); the_excerpt(); endwhile; else: _e( 'Sorry, no posts matched your criteria.', 'textdomain' ); endif; ?> ``` #### Individual Post In WordPress, each post has its own page, which displays the relevant information for that post. Template tags allow you to customize which information you want to display. In the example below, the loop outputs the post’s title and content. You could use this example in a post or page template file to display the most basic information about the post. You could also customize this template to add more data to the post, for example the category. ```php ', '' ); the_content(); endwhile; else: _e( 'Sorry, no pages matched your criteria.', 'textdomain' ); endif; ?> ``` ### Intermediate Examples #### Style Posts from Some Categories Differently The example below does a couple of things: - First, it displays each post with its title, time, author, content, and category, similar to the individual post example above. - Next, it makes it possible for posts with the category ID of “3” to be styled differently, utilizing the `in_category()` template tag. Code comments in this example provide details throughout each stage of the loop: ```php
', ';' ); // Display a link to other posts by this posts author. printf( __( 'Posted by %s', 'textdomain' ), get_the_author_posts_link() ); // Display the post's content in a div. ?>
``` ## Multiple Loops In some situations, you may need to use more than one loop. For example you may want to display the titles of the posts in a table of content list at the top of the page and then display the content further down the page. Since the query isn’t being changed we simply need to rewind the loop when we need to loop through the posts for a second time. For that we will use the function [rewind\_posts()](https://developer.wordpress.org/reference/functions/rewind_posts/) . ### Using rewind\_posts You can use `rewind_posts()` to loop through the *same* query a second time. This is useful if you want to display the same query twice in different locations on a page. Here is an example of `rewind_posts()` in use: ```php ``` ### Creating secondary queries and loops Using two loops with the same query was relatively easy but not always what you will need. Instead, you will often want to create a secondary query to display different content on the template. For example, you might want to display two groups of posts on the same page, but do different things to each group. A common example of this, as shown below, is displaying a single post with a list of posts from the same category below the single post. ```php have_posts() ) echo '
    '; while ( $secondary_query->have_posts() ) : $secondary_query->the_post(); the_title( '
  • ', '
  • ' ); endwhile; echo '
'; endif; wp_reset_postdata(); ?> ``` As you can see in the example above, we first display a regular loop. Then we define a new variable that uses `WP_Query` to query a specific category; in our case, we chose the `example-category` slug. Note that the regular loop in the example above has one difference: it calls `wp_reset_postdata()` to reset the post data. Before you can use a second loop, you need to reset the post data. There are two ways to do this: 1. By using the `rewind_posts()` function; or 2. By creating new query objects. ### Resetting multiple loops It’s important when using multiple loops in a template that you reset them. Not doing so can lead to unexpected results due to how data is stored and used within the ``global `$post` variable. There are three main ways to reset the loop depending on the way they are called. - ```wp_reset_postdata()` - `wp_reset_query()` - `rewind_posts()` ### Using wp\_reset\_postdata Use `wp_reset_postdata()` when you are running custom or multiple loops with `WP_Query`. This function restores the global `$post` variable to the current post in the main query. If you’re following best practices, this is the most common function you will use to reset loops. To properly use this function, place the following code after any loops with `WP_Query`: ```php ``` Here is an example of a loop using `WP_Query` that is reset with `wp_reset_postdata()`. ```php 3 ); // Variable to call WP_Query. $the_query = new WP_Query( $args ); if ( $the_query->have_posts() ) : // Start the Loop while ( $the_query->have_posts() ) : $the_query->the_post(); the_title(); the_excerpt(); // End the Loop endwhile; else: // If no posts match this query, output this text. _e( 'Sorry, no posts matched your criteria.', 'textdomain' ); endif; wp_reset_postdata(); ?> ``` ### Using wp\_reset\_query Using `wp_reset_query()` restores the [WP\_Query](https://developer.wordpress.org/reference/classes/wp_query/) and global `$post` data to the original main query. You **MUST** use this function to reset your loop if you use `query_posts()` within your loop. You can use it after custom loops with [WP\_Query](https://developer.wordpress.org/reference/classes/wp_query/) because it actually calls `wp_reset_postdata()` when it runs. However, it’s best practice to use `wp_reset_postdata()` with any custom loops involving `WP_Query`. `query_posts()` is *not best practice* and should be avoided if at all possible. Therefore, you shouldn’t have much use for `wp_reset_query()`. To properly use this function, place the following code after any loops with `query_posts()`. ```php ``` --- # Theme Functions Source: https://developer.wordpress.org/themes/basics/theme-functions/ `Functions.php` can be used by both classic themes, block themes, and child themes. The `functions.php` file is where you add unique features to your WordPress theme. It can be used to hook into the core functions of WordPress to make your theme more modular, extensible, and functional. ## What is `functions.php`? The `functions.php` file behaves like a WordPress plugin, adding features and functionality to a WordPress site. You can use it to call WordPress functions and to define your own functions. The same result can be produced using either a plugin or `functions.php`. If you are creating new features that should be available no matter what the website looks like, **it is best practice to put them in a plugin**. There are advantages and tradeoffs to either using a WordPress plugin or using `functions.php`. A WordPress plugin: - requires specific, unique header text; - is stored in wp-content/plugins, usually in a subdirectory; - only executes on page load when activated; - applies to all themes; and - should have a single purpose – for example, offer search engine optimization features or help with backups. Meanwhile, a `functions.php` file: - requires no unique header text; - is stored in theme’s subdirectory in wp-content/themes; - executes only when in the active theme’s directory; - applies only to that theme (if the theme is changed, the features can no longer be used); and - can have numerous blocks of code used for many different purposes. Each theme has its own functions file, but only code in the active theme’s `functions.php` is actually run. If your theme already has a functions file, you can add code to it. If not, you can create a plain-text file named `functions.php` to add to your theme’s directory, as explained below. A [child theme](https://developer.wordpress.org/themes/advanced-topics/child-themes/) can have its own `functions.php` file. Adding a function to the child functions file is a risk-free way to modify a parent theme. That way, when the parent theme is updated, you don’t have to worry about your newly added function disappearing. Although the child theme’s `functions.php` is loaded by WordPress right before the parent theme’s `functions.php`, it does not *override* it. The child theme’s `functions.php` can be used to augment or replace the parent theme’s functions. Similarly, `functions.php` is loaded *after any plugin files have loaded*. With `functions.php` you can: - Use WordPress hooks. For example, with [the `excerpt_length`](https://developer.wordpress.org/reference/hooks/excerpt_length/) filter you can change your post excerpt length (from default of 55 words). - Enable WordPress features with `add_theme_support()`. For example, turn on post thumbnails, post formats, and navigation menus. - Define functions you wish to reuse in multiple theme template files. In WordPress, naming conflicts can occur when two or more functions, classes, or variables have the same name. This can cause errors or unexpected behavior in a WordPress site. It is the responsibility of both the theme developer and plugin developer to avoid naming conflicts in their respective code. Theme developers should ensure that their functions, classes, and variables have unique names that do not conflict with those used by WordPress core or other plugins. They should also prefix their function and class names with a unique identifier, such as the theme name or abbreviation, to minimize the chances of a naming conflict. ## Examples Below are a number of examples that you can use in your functions.php file to support various features. Each of these examples are allowed in your theme if you choose to submit it to the WordPress.org theme directory. ### Theme Setup A number of theme features should be included within a “setup” function that runs initially when your theme is activated. As shown below, each of these features can be added to your `functions.php` file to activate recommended WordPress features. It’s important to namespace your functions with your theme name. All examples below use `myfirsttheme_` as their namespace, which should be customized based on your theme name. To create this initial function, start a new function entitled `myfirsttheme_setup()`, like so: ```php if ( ! function_exists( 'myfirsttheme_setup' ) ) : /** * Sets up theme defaults and registers support for various WordPress * features. * * It is important to set up these functions before the init hook so * that none of these features are lost. * * @since MyFirstTheme 1.0 */ function myfirsttheme_setup() { ... } ``` Note: In the above example, the function myfirsttheme\_setup is started but not closed out. Be sure to close out your functions. #### Automatic Feed Links Automatic feed links enables post and comment RSS feeds by default. These feeds will be displayed in `` automatically. They can be called using `add_theme_support()` in classic themes. This feature is automatically enabled for block themes, and does not need to be included during theme setup. ```php add_theme_support( 'automatic-feed-links' ); ``` #### Navigation Menus In classic themes, custom [navigation menus](https://developer.wordpress.org/themes/functionality/navigation-menus/ "Navigation Menus") allow users to edit and customize menus in the Menus admin panel, giving users a drag-and-drop interface to edit the various menus in their theme. You can set up multiple menus in `functions.php`. They can be added using `register_nav_menus()` and inserted into a theme using `wp_nav_menu()`, as discussed [later in this handbook](https://developer.wordpress.org/themes/functionality/navigation-menus/). If your theme will allow more than one menu, you should use an array. While some themes will not have custom navigation menus, it is recommended that you allow this feature for easy customization. ```php register_nav_menus( array( 'primary' => __( 'Primary Menu', 'myfirsttheme' ), 'secondary' => __( 'Secondary Menu', 'myfirsttheme' ) ) ); ``` Each of the menus you define can be called later using `wp_nav_menu()` and using the name assigned (i.e. primary) as the `theme_location` parameter. In block themes, you use the [navigation block](https://wordpress.org/support/article/navigation-block/) instead. #### Load Text Domain Themes can be translated into multiple languages by making the strings in your theme available for translation. To do so, you must use `load_theme_textdomain()`. For more information on making your theme available for translation, read the [internationalization](https://developer.wordpress.org/themes/functionality/internationalization/ "Internationalization & Text Domains") section. ```php load_theme_textdomain( 'myfirsttheme', get_template_directory() . '/languages' ); ``` #### Post Thumbnails [Post thumbnails and featured images](https://developer.wordpress.org/themes/functionality/featured-images-post-thumbnails/ "Featured Images & Post Thumbnails") allow your users to choose an image to represent their post. Your theme can decide how to display them, depending on its design. For example, you may choose to display a post thumbnail with each post in an archive view. Or, you may want to use a large featured image on your homepage. This feature is automatically enabled for block themes, and does not need to be included during theme setup. ```php add_theme_support( 'post-thumbnails' ); ``` #### Post Formats [Post formats](https://developer.wordpress.org/themes/functionality/post-formats/ "Post Formats") allow users to format their posts in different ways. This is useful for allowing bloggers to choose different formats and templates based on the content of the post. `add_theme_support()` is also used for Post Formats. This is **recommended**. ```php add_theme_support( 'post-formats', array( 'aside', 'gallery', 'quote', 'image', 'video' ) ); ``` [Learn more about post formats.](https://developer.wordpress.org/themes/functionality/post-formats/) #### Theme support in block themes In block themes, the following theme supports are enabled automatically: ```php add_theme_support( 'post-thumbnails' ); add_theme_support( 'responsive-embeds' ); add_theme_support( 'editor-styles' ); add_theme_support( 'html5', array( 'style','script' ) ); add_theme_support( 'automatic-feed-links' ); ``` #### Initial Setup Example Including all of the above features will give you a `functions.php` file like the one below. Code comments have been added for future clarity. As shown at the bottom of this example, you must add the required `add_action()` statement to ensure the `myfirsttheme_setup` function is loaded. ```php if ( ! function_exists( 'myfirsttheme_setup' ) ) : /** * Sets up theme defaults and registers support for various * WordPress features. * * Note that this function is hooked into the after_setup_theme * hook, which runs before the init hook. The init hook is too late * for some features, such as indicating support post thumbnails. */ function myfirsttheme_setup() { /** * Make theme available for translation. * Translations can be placed in the /languages/ directory. */ load_theme_textdomain( 'myfirsttheme', get_template_directory() . '/languages' ); /** * Add default posts and comments RSS feed links to . */ add_theme_support( 'automatic-feed-links' ); /** * Enable support for post thumbnails and featured images. */ add_theme_support( 'post-thumbnails' ); /** * Add support for two custom navigation menus. */ register_nav_menus( array( 'primary' => __( 'Primary Menu', 'myfirsttheme' ), 'secondary' => __( 'Secondary Menu', 'myfirsttheme' ), ) ); /** * Enable support for the following post formats: * aside, gallery, quote, image, and video */ add_theme_support( 'post-formats', array( 'aside', 'gallery', 'quote', 'image', 'video' ) ); } endif; // myfirsttheme_setup add_action( 'after_setup_theme', 'myfirsttheme_setup' ); ``` ### Content Width In classic themes, a content width is added to your `functions.php` file to ensure that no content or assets break the container of the site. The content width sets the maximum allowed width for any content added to your site, including uploaded images. In the example below, the content area has a maximum width of 800 pixels. No content will be larger than that. ```php if ( ! isset ( $content_width) ) { $content_width = 800; } ``` Themes that include a theme.json configuration file does not need to include the variable in functions.php. Instead, the content width is added to the layout setting in theme.json. You can [learn more about using theme.json in the advanced section](https://developer.wordpress.org/themes/advanced-topics/theme-json/). ### Other Features There are other common features you can include in `functions.php`. Listed below are some of the most common features. Click through and learn more about each of these features. - [Custom Headers](https://developer.wordpress.org/themes/functionality/custom-headers/) **-Classic themes** - [Sidebars](https://developer.wordpress.org/themes/functionality/sidebars/) (widget areas) **-Classic themes** - Custom Background **-Classic themes** - Title tag **-Classic themes** - Add Editor Styles - HTML5 **-Classic themes** ## Your *functions.php* File If you choose to include all the functions listed above, this is what your *functions.php* might look like. It has been commented with references to above. ```php /** * MyFirstTheme's functions and definitions * * @package MyFirstTheme * @since MyFirstTheme 1.0 */ /** * First, let's set the maximum content width based on the theme's * design and stylesheet. * This will limit the width of all uploaded images and embeds. */ if ( ! isset( $content_width ) ) { $content_width = 800; /* pixels */ } if ( ! function_exists( 'myfirsttheme_setup' ) ) : /** * Sets up theme defaults and registers support for various * WordPress features. * * Note that this function is hooked into the after_setup_theme * hook, which runs before the init hook. The init hook is too late * for some features, such as indicating support post thumbnails. */ function myfirsttheme_setup() { /** * Make theme available for translation. * Translations can be placed in the /languages/ directory. */ load_theme_textdomain( 'myfirsttheme', get_template_directory() . '/languages' ); /** * Add default posts and comments RSS feed links to . */ add_theme_support( 'automatic-feed-links' ); /** * Enable support for post thumbnails and featured images. */ add_theme_support( 'post-thumbnails' ); /** * Add support for two custom navigation menus. */ register_nav_menus( array( 'primary' => __( 'Primary Menu', 'myfirsttheme' ), 'secondary' => __( 'Secondary Menu', 'myfirsttheme' ), ) ); /** * Enable support for the following post formats: * aside, gallery, quote, image, and video */ add_theme_support( 'post-formats', array( 'aside', 'gallery', 'quote', 'image', 'video' ) ); } endif; // myfirsttheme_setup add_action( 'after_setup_theme', 'myfirsttheme_setup' ); ``` --- # Linking Theme Files & Directories Source: https://developer.wordpress.org/themes/basics/linking-theme-files-directories/ ## Linking to Core Theme Files As you’ve learned, WordPress themes are built from a number of different template files. At the very least this will usually include a `sidebar.php`, `header.php` and `footer.php`. These are called using [Template Tags](https://developer.wordpress.org/themes/basics/template-tags/ "Template Tags"), for example: - [get\_header()](https://developer.wordpress.org/reference/functions/get_header/) ; - [get\_footer()](https://developer.wordpress.org/reference/functions/get_footer/) ; - [get\_sidebar()](https://developer.wordpress.org/reference/functions/get_sidebar/) ; You can create custom versions of these files can be called as well by naming the file `sidebar-{your_custom_template}.php`, `header-{your_custom_template}.php` and `footer-{your_custom_template}.php`. You can then use Template Tags with the custom template name as the only parameter, like this: ```php get_header( 'your_custom_template' ); get_footer( 'your_custom_template' ); get_sidebar( 'your_custom_template' ); ``` WordPress creates pages by assembling various files. Aside from the standard files for the header, footer and sidebar, you can create custom template files and call them at any location in the page using [get\_template\_part()](https://developer.wordpress.org/reference/functions/get_template_part/) . To create a custom template file in your theme give the file an appropriate name and use the same custom template system as with the header, sidebar and footer files: ```php slug-template.php ``` For example, if you would like to create a custom template to handle your post content you could create a template file called `content.php` and then add a specific content layout for product content by extending the file name to `content-product.php`. You would then load this template file in your theme like this: ```php get_template_part( 'content', 'product' ); ``` If you want to add more organization to your templates, you can place them in their own directories within your theme directory. For example, suppose you add a couple more *content* templates for *profiles* and *locations*, and group them in their own directory called `content-templates`. The theme hierarchy for your theme called `my-theme` might look like the following. `style.css` and `page.php` are included for context. - themes - my-theme - content-templates - content-location.php - content-product.php - content-profile.php - style.css To include your content templates, prepend the directory names to the `slug` argument like this: ```php get_template_part( 'content-templates/content', 'location' ); get_template_part( 'content-templates/content', 'product' ); get_template_part( 'content-templates/content', 'profile' ); ``` ## Linking to Theme Directories To link to the theme’s directory, you can use the following function: - [get\_theme\_file\_uri()](https://developer.wordpress.org/reference/functions/get_theme_file_uri/) ; If you are not using a child theme, this function will return the full URI to your theme’s main folder. You can use this to reference sub-folders and files in your theme like this: ```php echo get_theme_file_uri( 'images/logo.png' ); ``` If you are using a child theme then this function will return the URI of the file in your child theme if it exists. If the file cannot be found in your child theme, the function will return the URI of the file in the parent theme. This is particularly important to keep in mind when distributing a theme or in any other case where a child theme may or may not be active. To access the path to a file in your theme’s directories, you can use the following function: - [get\_theme\_file\_path()](https://developer.wordpress.org/reference/functions/get_theme_file_path/) ; Like [get\_theme\_file\_uri()](https://developer.wordpress.org/reference/functions/get_theme_file_uri/) , this will access the path of the file in the child theme if it exists. If the file cannot be found in the child theme, the function will access the path to the file in the parent theme. In a child theme, you can link to a file URI or path in the parent theme’s directories using the following functions: - [get\_parent\_theme\_file\_uri()](https://developer.wordpress.org/reference/functions/get_parent_theme_file_uri/) ; - [get\_parent\_theme\_file\_path()](https://developer.wordpress.org/reference/functions/get_parent_theme_file_path/) ; As with `get_theme_file_uri(),` you can reference sub-folders and files like this: ```php echo get_parent_theme_file_uri( 'images/logo.png' ); //or echo get_parent_theme_file_path( 'images/logo.png' ); ``` Take care when referencing files that may not be present, as these functions will return the URI or file path whether the file exists or not. If the file is missing, these functions will return a broken link. The functions [get\_theme\_file\_uri()](https://developer.wordpress.org/reference/functions/get_theme_file_uri/) , [get\_theme\_file\_path()](https://developer.wordpress.org/reference/functions/get_theme_file_path/) , [get\_parent\_theme\_file\_uri()](https://developer.wordpress.org/reference/functions/get_parent_theme_file_uri/) , [get\_parent\_theme\_file\_path()](https://developer.wordpress.org/reference/functions/get_parent_theme_file_path/) were introduced in WordPress 4.7. For previous WordPress versions, use [get\_template\_directory\_uri()](https://developer.wordpress.org/reference/functions/get_template_directory_uri/) , [get\_template\_directory()](https://developer.wordpress.org/reference/functions/get_template_directory/) , [get\_stylesheet\_directory\_uri()](https://developer.wordpress.org/reference/functions/get_stylesheet_directory_uri/) , [get\_stylesheet\_directory()](https://developer.wordpress.org/reference/functions/get_stylesheet_directory/) . Take note that the newer 4.7 functions run the older functions anyway as part of the checking process so it makes sense to use the newer functions when possible. ## Dynamic Linking in Templates Regardless of your permalink settings, you can link to a page or post dynamically by referring to its unique numerical ID (seen in several pages in the admin interface) with ```php This is a link ``` This is a convenient way to create page menus as you can later change page slugs without breaking links, as IDs will stay the same. However, this might increase database queries. --- # Including CSS & JavaScript (Archived) Source: https://developer.wordpress.org/themes/basics/including-css-javascript/ This is an old page that has been archived in favor of the newer [Including Assets documentation](https://developer.wordpress.org/themes/core-concepts/including-assets/) in the Core Concepts chapter. This page will eventually be removed and redirect to the newer doc. When you’re creating your theme, you may want to create additional stylesheets or JavaScript files. However, remember that a WordPress website will not just have your theme active, it will also be using many different plugins. So that everything works harmoniously, it’s important that theme and plugins load scripts and stylesheets using the standard WordPress method. This will ensure the site remains efficient and that there are no incompatibility issues. Adding scripts and styles to WordPress is a fairly simple process. Essentially, you will create a function that will enqueue all of your scripts and styles. When enqueuing a script or stylesheet, WordPress creates a handle and path to find your file and any dependencies it may have (like jQuery) and then you will use a hook that will insert your scripts and stylesheets. ## Enqueuing Scripts and Styles The proper way to add scripts and styles to your theme is to enqueue them in the `functions.php` files. The `style.css` file is required in all themes, but it may be necessary to add other files to extend the functionality of your theme. Tip: WordPress includes a number of JavaScript files as part of the software package, including commonly used libraries such as jQuery. Before adding your own JavaScript, [check to see if you can make use of an included library](https://developer.wordpress.org/themes/basics/including-css-javascript/#default-scripts-included-and-registered-by-wordpress). The basics are: 1. Enqueue the script or style using `wp_enqueue_script()`, `wp_enqueue_style()`, or `wp_enqueue_block_style`. ### Stylesheets Your CSS stylesheets are used to customize the presentation of your theme. A stylesheet is also the file where information about your theme is stored. For this reason, the `style.css` file is **required in every theme.** Rather then loading the stylesheet in your `header.php` file, you should load it in using `wp_enqueue_style`. In order to load your main stylesheet, you can enqueue it in `functions.php` To enqueue `style.css`: ```php wp_enqueue_style( 'style', get_stylesheet_uri() ); ``` This will look for a stylesheet named “style” and load it. The basic function for enqueuing a style is: ```php wp_enqueue_style( $handle, $src, $deps, $ver, $media ); ``` You can include these parameters: - **$handle** is simply the name of the stylesheet. - **$src** is where it is located. The rest of the parameters are optional. - **$deps** refers to whether or not this stylesheet is dependent on another stylesheet. If this is set, this stylesheet will not be loaded unless its dependent stylesheet is loaded first. - **$ver** sets the version number. - **$media** can specify which type of media to load this stylesheet in, such as ‘all’, ‘screen’, ‘print’ or ‘handheld.’ So if you wanted to load a stylesheet named “slider.css” in a folder named “CSS” in you theme’s root directory, you would use: ```php wp_enqueue_style( 'slider', get_template_directory_uri() . '/css/slider.css', false, '1.1', 'all'); ``` ## Including CSS for block styles In addition to `wp_enqueue_style()`, you can use `wp_enqueue_block_style()` to enqueue styles for blocks. [wp\_enqueue\_block\_style()](https://developer.wordpress.org/reference/functions/wp_enqueue_block_style/) requires WordPress version 5.9 or later. A key part of creating block themes is performance. With, `wp_enqueue_block_style()`, the theme only loads the CSS for the selected block when the block is used on the page. The additional style is loaded in the editor and the front, after the block style provided by WordPress and the Gutenberg plugin. You can use this method to add block styles that you can not add via `theme.json`. For example, media queries. This code example changes the size and text color of the date in the latest comments block. Because this is a `time` HTML element that is nested inside other HTML elements, can not be styled using `theme.json`. First, create a new CSS file with the name of the block: `latest-comments.css`. Where you place the file depends on how you organize your theme files. In the example, the file is placed inside the folders `assets/CSS/blocks`. The CSS class for the time element is `wp-block-latest-comments__comment-date`. The prefix and the block name are followed by the partial, separated by two underscores. You can read more about the naming convention for the block editor in the [coding guidelines](https://developer.wordpress.org/block-editor/contributors/code/coding-guidelines/#naming). The text color and font size are added with CSS custom properties that are generated from `theme.json`: ```css .wp-block-latest-comments__comment-date { color: var(--wp--preset--color--primary); font-size: var(--wp--preset--font-size--small); } ``` Next, enqueue the block style inside the themes setup function. The block name is placed inside an array to load more than one block style. A `foreach` loop walks through each block in the array and creates a handle, src (source), and path argument. `wp_enqueue_block_style()` then enqueues the file using the block name and argument: `wp_enqueue_block_style( "prefix/blockname", $args );` In the code example, the prefix is “core” since the style is for a core block. When you style blocks from plugins, you need to adjust the prefix. ```php function myfirsttheme_setup() { /* * Load additional block styles. */ $styled_blocks = ['latest-comments']; foreach ( $styled_blocks as $block_name ) { $args = array( 'handle' => "myfirsttheme-$block_name", 'src' => get_theme_file_uri( "assets/css/blocks/$block_name.css" ), $args['path'] = get_theme_file_path( "assets/css/blocks/$block_name.css" ), ); wp_enqueue_block_style( "core/$block_name", $args ); } } add_action( 'after_setup_theme', 'myfirsttheme_setup' ); ``` ### Scripts Any additional JavaScript files required by a theme should be loaded using `wp_enqueue_script`. This ensures proper loading and caching, and allows the use conditional tags to target specific pages. These are **optional**. `wp_enqueue_script` uses a similar syntax to `wp_enqueue_style`. Enqueue your script: ```php wp_enqueue_script( $handle, $src, $deps, $ver, $args ); ``` - **$handle** is the name for the script. - **$src** defines where the script is located. - **$deps** is an array that can handle any script that your new script depends on, such as jQuery. - **$ver** lets you list a version number. - **$args** an array of arguments that define footer printing (via an `in_footer` key) and script loading strategies (via a `strategy` key) such as `defer` or `async`. This replaces/overloads the `$in_footer` parameter as of WordPress version 6.3. Your enqueue function may look like this: ```php wp_enqueue_script( 'script', get_template_directory_uri() . '/js/script.js', array( 'jquery' ), 1.1, true); ``` ### Delayed Script Loading WordPress provides support for specifying a script loading strategy via the `wp_register_script()` and `wp_enqueue_script()` functions, by way of the `strategy` key within the new `$args` array parameter introduced in WordPress 6.3. Supported strategies are as follows: - **defer** - Added by specifying an array key value pair of `'strategy' => 'defer'` to the $args parameter. - Scripts marked for deferred execution — via the `defer` script attribute — are only executed once the DOM tree has fully loaded (but before the `DOMContentLoaded` and window load events). Deferred scripts are executed in the same order they were printed/added in the DOM, unlike asynchronous scripts. - **async** - Added by specifying an array key value pair of `'strategy' => 'async'` to the `$args` parameter. - Scripts marked for asynchronous execution — via the `async` script attribute — are executed as soon as they are loaded by the browser. Asynchronous scripts do not have a guaranteed execution order, as script B (although added to the DOM after script A) may execute first given that it may complete loading prior to script A. Such scripts may execute either before the DOM has been fully constructed or after the `DOMContentLoaded` event. Following is an example of specifying a loading strategy during script registration: ```php wp_register_script( 'foo', '/path/to/foo.js', array(), '1.0.0', array( 'strategy' => 'defer', ) ); ``` The same approach applies when using `wp_enqueue_script()`. When specifying a delayed script loading strategy, consideration of the script’s dependency tree (its dependencies and/or dependents) is taken into account when deciding on an “eligible strategy” so as not to result in application of a strategy that is valid for one script but detrimental to others in the tree by causing an unintended out of order of execution. As a result of such logic, the intended loading strategy that you pass via the `$args` parameter may not be the final (chosen) strategy, but it will never be detrimental to (or stricter than) the intended strategy. ### The Comment Reply Script WordPress comments have quite a bit of functionality in them right out of the box, including threaded comments and enhanced comment forms. In order for comments to work properly, they require some JavaScript. However, since there are certain options that need to be defined within this JavaScript, the comment-reply script should be added to every classic theme that uses comments. **In block themes, the script is included when you place a comment block. You do not need to add it manually.** The proper way to include comment reply in classic themes is to use conditional tags to check if certain conditions exist, so that the script isn’t being loaded unnecessarily. For instance, you can only load scripts on single post pages using `is_singular`, and check to make sure that “Enable threaded comments” is selected by the user. So you can set up a function like: ```php if ( is_singular() && comments_open() && get_option( 'thread_comments' ) ) { wp_enqueue_script( 'comment-reply' ); } ``` If comments are enabled by the user, and we are on a post page, then the comment reply script will be loaded. Otherwise, it will not. ### Combining Enqueue Functions It is best to combine all enqueued scripts and styles into a single function, and then call them using the `wp_enqueue_scripts` action. This function and action should be located somewhere below the initial setup (performed above): ```php function add_theme_scripts() { wp_enqueue_style( 'style', get_stylesheet_uri() ); wp_enqueue_style( 'slider', get_template_directory_uri() . '/css/slider.css', array(), '1.1', 'all' ); wp_enqueue_script( 'script', get_template_directory_uri() . '/js/script.js', array( 'jquery' ), 1.1, true ); if ( is_singular() && comments_open() && get_option( 'thread_comments' ) ) { wp_enqueue_script( 'comment-reply' ); } } add_action( 'wp_enqueue_scripts', 'add_theme_scripts' ); ``` ## Default Scripts Included and Registered by WordPress By default, WordPress includes many popular scripts commonly used by web developers, as well as the scripts used by WordPress itself. Some of them are listed on this reference page: > [wp\_enqueue\_script()](https://developer.wordpress.org/reference/functions/wp_enqueue_script/) **The list is far from complete.** You can find a full list of included files in [wp-includes/script-loader.php](https://core.trac.wordpress.org/browser/trunk/src/wp-includes/script-loader.php). / Changelog: - Updated 2023-02-24: Added information about [wp\_enqueue\_block\_style()](https://developer.wordpress.org/reference/functions/wp_enqueue_block_style/) . - Updated 2024-06-06: Added alert to point readers to new doc. --- # Conditional Tags Source: https://developer.wordpress.org/themes/basics/conditional-tags/ Conditional Tags can be used in your Template Files in classic themes to alter the display of content depending on the conditions that the current page matches. They tell WordPress what code to display under specific conditions. Conditional Tags usually work with PHP [if](http://php.net/manual/en/control-structures.if.php "PHP if conditional") /[else](http://php.net/manual/en/control-structures.else.php "PHP else conditional") Conditional Statements. The code begins by checking to see **if** a statement is true or false. If the statement is found to be true, the first set of code is executed. If it’s false, the first set of code is skipped, and the second set of code (after the **else**) is executed instead. For example, you could ask if a user is logged in, and then provide a different greeting depending on the result. ```php if ( is_user_logged_in() ) : echo 'Welcome, registered user!'; else : echo 'Welcome, visitor!'; endif; ``` Note the close relation these tags have to [WordPress Template Hierarchy](https://developer.wordpress.org/themes/basics/template-hierarchy/). ## Where to Use Conditional Tags For a Conditional Tag to modify your data, the information must already have been retrieved from your database, i.e. the query must have already run. If you use a Conditional Tag before there is data, there’ll be nothing to ask the if/else statement about. It’s important to note that WordPress loads `functions.php` before the query is run, so if you simply include a Conditional Tag in that file, it won’t work. Two ways to implement Conditional Tags: - place it in a [Template File](https://developer.wordpress.org/themes/basics/template-files/) - create a function out of it in `functions.php` that hooks into an action/filter that triggers at a later point ## The Conditions For Listed below are the conditions under which each of the following **conditional statements proves to be true**. Tags which can accept parameters are noted. ### The Main Page [is\_home()](https://developer.wordpress.org/reference/functions/is_home/ "Function_Reference/is_home") This condition returns true when the main blog page is being displayed, usually in standard reverse chronological order. If your home page has been set to a Static Page instead, then this will only prove true on the page which you set as the “Posts page” in Settings > Reading. ### The Front Page [is\_front\_page()](https://developer.wordpress.org/reference/functions/is_front_page/ "Function_Reference/is_front_page") This condition returns true when the front page of the site is displayed, regardless of whether it is set to show posts or a static page. Returns true when: 1. the main blog page is being displayed **and** 2. the Settings > Reading -> *Front page displays* option is set to *Your latest posts* **OR** 1. when Settings > Reading -> *Front page displays* is set to *A static page* **and** 2. the Front Page value is the current Page being displayed. ### The Administration Panels [is\_admin()](https://developer.wordpress.org/reference/functions/is_admin/ "Function_Reference/is_admin") This condition returns true when the Dashboard or the administration panels are being displayed. ### A Single Post Page [is\_single()](https://developer.wordpress.org/reference/functions/is_single/ "Function_Reference/is_single") Returns true when any single Post (or attachment, or custom Post Type) is being displayed. This condition returns false if you are on a page. ```php is_single( '17' ); ``` [is\_single()](https://developer.wordpress.org/reference/functions/is_single/) can also check for certain posts by ID and other parameters. The above example proves true when Post 17 is being displayed as a single Post. ```php is_single( 'Irish Stew' ); ``` Parameters include Post titles, as well. In this case, it proves true when the Post with title “Irish Stew” is being displayed as a single Post. ```php is_single( 'beef-stew' ); ``` Proves true when the Post with Post Slug “beef-stew” is being displayed as a single Post. ```php is_single( array( 17, 'beef-stew', 'Irish Stew' ) ); ``` Returns true when the single post being displayed is either post ID 17, or the post\_name is “beef-stew”, or the post\_title is “Irish Stew”. ```php is_single( array( 17, 19, 1, 11 ) ); ``` Returns true when the single post being displayed is either post ID = 17, post ID = 19, post ID = 1 or post ID = 11. ```php is_single( array( 'beef-stew', 'pea-soup', 'chilli' ) ); ``` Returns true when the single post being displayed is either the post\_name “beef-stew”, post\_name “pea-soup” or post\_name “chilli”. ```php is_single( array( 'Beef Stew', 'Pea Soup', 'Chilli' ) ); ``` Returns true when the single post being displayed is either the post\_title is “Beef Stew”, post\_title is “Pea Soup” or post\_title is “Chilli”. Note: This function does not distinguish between the post ID, post title, or post name. A post named “17” would be displayed if a post ID of 17 was requested. Presumably the same holds for a post with the slug “17”. ### A Single Post, Page, or Attachment [is\_singular()](https://developer.wordpress.org/reference/functions/is_singular/) Returns true for any is\_single, is\_page, and is\_attachment. It does allow testing for post types. ### A Sticky Post [is\_sticky()](https://developer.wordpress.org/reference/functions/is_sticky/ "Function_Reference/is_sticky") Returns true if the “Stick this post to the front page” check box has been checked for the current post. In this example, no post ID argument is given, so the post ID for the Loop post is used. ```php is_sticky( '17' ); ``` Returns true when Post 17 is considered a sticky post. ### A Post Type [get\_post\_type()](https://developer.wordpress.org/reference/functions/get_post_type/ "Function_Reference/get_post_type") You can test to see if the current post is of a certain type by including [get\_post\_type()](https://developer.wordpress.org/reference/functions/get_post_type/ "Function Reference/get_post_type") in your conditional. It’s not really a conditional tag, but it returns the [registered post type](https://developer.wordpress.org/reference/functions/register_post_type/ "Function Reference/Register Post Type") of the current post. ```php if ( 'book' == get_post_type() ) { ... } ``` [post\_type\_exists() ](https://developer.wordpress.org/reference/functions/post_type_exists/ "Function Reference/post_type_exists") Returns true if a given post type is a registered post type. This does not test if a post is a certain post\_type. Note: This function replaces a function called is\_post\_type which existed briefly in 3.0 development. ### A Post Type is Hierarchical [is\_post\_type\_hierarchical( $post\_type ) ](https://developer.wordpress.org/reference/functions/is_post_type_hierarchical/ "Function-reference/is_post_type_hierarchical/") Returns true if this $post\_type has been set with hierarchical support when registered. ```php is_post_type_hierarchical( 'book' ); ``` Returns true if the book post type was registered as having support for hierarchical. ### A Post Type Archive [is\_post\_type\_archive()](https://developer.wordpress.org/reference/functions/is_post_type_archive/ "Function_Reference/is_post_type_archive") Returns true on any post type archive. ```php is_post_type_archive( $post_type ); ``` Returns true if on a post type archive page that matches $post\_type (can be a single post type or an array of post types). To turn on post type archives, use ‘has\_archive’ => true, when [registering the post type](https://make.wordpress.org/docs/plugin-developer-handbook/9-custom-post-types-and-taxonomies/registering-custom-post-types/ "Function_Reference/register_post_type"). ### Any Page Containing Posts [comments\_open()](https://developer.wordpress.org/reference/functions/comments_open/ "Function_Reference/comments_open") When comments are allowed for the current Post being processed in the [WordPress Loop](https://make.wordpress.org/docs/theme-developer-handbook/part-one-theme-basics/the-loop/ "The Loop"). [pings\_open()](https://developer.wordpress.org/reference/functions/pings_open/ "Function_Reference/pings_open") When pings are allowed for the current Post being processed in the WordPress Loop. ### A “PAGE” Page This section refers to WordPress Pages, not any generic webpage from your blog, or in other words to the built in *post\_type* ‘page’. [is\_page()](https://developer.wordpress.org/reference/functions/is_page/ "Function_Reference/is_page") When any Page is being displayed. ```php is_page( '42' ); ``` When Page 42 (ID) is being displayed. ```php is_page( 'About Me And Joe' ); ``` When the Page with a *post\_title* of “About Me And Joe” is being displayed. ```php is_page( 'about-me' ); ``` When the Page with a *post\_name* (slug) of “about-me” is being displayed. ```php is_page( array( 42, 'about-me', 'About Me And Joe' ) ); ``` Returns true when the Pages displayed is either *post ID* = 42, or *post\_name* is “about-me”, or *post\_title* is “About Me And Joe”. ```php is_page( array( 42, 54, 6 ) ); ``` Returns true when the Pages displayed is either *post ID* = 42, or *post ID* = 54, or *post ID* = 6. #### Testing for Paginated Pages You can use this code to check whether you’re on the nth page in a Post or Page that has been divided into pages using the `\ `QuickTag. This can be useful, for example, if you wish to display meta-data only on the first page of a post divided into several pages. ##### Example 1 ```php get( 'page' ); if ( ! $paged || $paged < 2 ) : // This is not a paginated page (or it's simply the first page of a paginated page/post) else : // This is a paginated page. endif; ``` ##### Example 2 ```php post_parent ) : // This is a subpage else : // This is not a subpage endif; ``` **Snippet 1** You can create your own is\_subpage() function using the code in Snippet 2. Add it to your functions.php file. It tests for a parent page in the same way as Snippet 1, but will return the ID of the page parent if there is one, or false if there isn’t. **Snippet 2** ```php post_parent ) { // return the ID of the parent post return $post->post_parent; // there is no parent so ... } else { // ... the answer to the question is false return false; } } ``` It is advisable to use a function like that in Snippet 2, rather than using the simple test like Snippet 1, if you plan to test for sub-pages frequently. To test if the parent of a page is a specific page, for instance “About” (page id pid 2 by default), we can use the tests in Snippet 3. These tests check to see if we are looking at the page in question, as well as if we are looking at any child pages. This is useful for setting variables specific to different sections of a web site, so a different banner image, or a different heading. **Snippet 3** ```php post_parent ) { $bannerimg = 'about.jpg'; } elseif ( is_page( 'learning' ) || '56' == $post->post_parent ) { $bannerimg = 'teaching.jpg'; } elseif ( is_page( 'admissions' ) || '15' == $post->post_parent ) { $bannerimg = 'admissions.jpg'; // Just in case we are at an unclassified page, perhaps the home page } else { $bannerimg = 'home.jpg'; } ``` Snippet 4 is a function that allows you to carry out the tests above more easily. This function will return true if we are looking at the page in question (so “About”) or one of its sub pages (so a page with a parent with ID “2”). **Snippet 4** Add Snippet 4 to your functions.php file, and call is\_tree( ‘id’ ) to see if the current page is the page, or is a sub page of the page. In Snippet 3, is\_tree( ‘2’ ) would replace “is\_page( ‘about’ ) || ‘2’ == $post->post\_parent” inside the first if tag. Note that if you have more than one level of pages the parent page is the one directly above and not the one at the very top of the hierarchy. ### Is a Page Template Allows you to determine whether or not you are in a page template or if a specific page template is being used. [is\_page\_template()](https://developer.wordpress.org/reference/functions/is_page_template/ "Function reference/page template") Is a Page Template being used? ```php is_page_template( 'about.php' ); ``` Is Page Template ‘about’ being used? Note that unlike other conditionals, if you want to specify a particular Page Template, you need to use the filename, such as about.php or my\_page\_template.php. Note: if the file is in a subdirectory you must include this as well. Meaning that this should be the filepath in relation to your theme as well as the filename, for example ‘page-templates/about.php’. ### A Category Page [is\_category()](https://developer.wordpress.org/reference/functions/is_category/ "Function reference/is category") When a Category archive page is being displayed. ```php is_category( '9' ); ``` When the archive page for Category 9 is being displayed. ```php is_category( 'Stinky Cheeses' ); ``` When the archive page for the Category with Name “Stinky Cheeses” is being displayed. ```php is_category( 'blue-cheese' ); ``` When the archive page for the Category with Category Slug “blue-cheese” is being displayed. ```php is_category( array( 9, 'blue-cheese', 'Stinky Cheeses' ) ); ``` Returns true when the category of posts being displayed is either term\_ID 9, or slug “blue-cheese”, or name “Stinky Cheeses”. ```php in_category( '5' ); ``` Returns true if the current post is in the specified category id. ```php in_category( array( 1, 2, 3 ) ); ``` Returns true if the current post is in either category 1, 2, or 3. ```php ! in_category( array( 4, 5, 6 ) ); ``` Returns true if the current post is NOT in either category 4, 5, or 6. Note the ! at the beginning. Note: Be sure to check your spelling when testing. There’s a big difference between “is” or “in”. See also [is\_archive()](https://developer.wordpress.org/reference/functions/is_archive/ "Function reference/is archive") and [Category Templates](https://make.wordpress.org/docs/theme-developer-handbook/part-one-theme-basics/template-hierarchy/#category "Template Hierarchy / Category templates"). ### A Tag Page [is\_tag()](https://developer.wordpress.org/reference/functions/is_tag/ "Function reference/is tag") When any Tag archive page is being displayed. ```php is_tag( 'mild' ); ``` When the archive page for tag with the slug of ‘mild’ is being displayed. ```php is_tag( array( 'sharp', 'mild', 'extreme' ) ); ``` Returns true when the tag archive being displayed has a slug of either “sharp”, “mild”, or “extreme”. ```php has_tag(); ``` When the current post has a tag. Must be used inside The Loop. ```php has_tag( 'mild' ); ``` When the current post has the tag ‘mild’. ```php has_tag( array( 'sharp', 'mild', 'extreme' ) ); ``` When the current post has any of the tags in the array. See also [is\_archive()](https://developer.wordpress.org/reference/functions/is_archive/ "Function Reference/is archive") and [Tag Templates](https://make.wordpress.org/docs/theme-developer-handbook/part-one-theme-basics/template-hierarchy/#tag "Template hierarchy/Tag template"). ### A Taxonomy Page [is\_tax()](https://developer.wordpress.org/reference/functions/is_tax/ "Function Reference/is tax") When any Taxonomy archive page is being displayed. ```php is_tax( 'flavor' ); ``` When a Taxonomy archive page for the flavor taxonomy is being displayed. ```php is_tax( 'flavor', 'mild'); ``` When the archive page for the flavor taxonomy with the slug of ‘mild’ is being displayed. ```php is_tax( 'flavor', array( 'sharp', 'mild', 'extreme' ) ); ``` Returns true when the flavor taxonomy archive being displayed has a slug of either “sharp”, “mild”, or “extreme”. [has\_term()](https://developer.wordpress.org/reference/functions/has_term/) Check if the current post has any of given terms. The first parameter should be an empty string. It expects a taxonomy slug/name as a second parameter. ```php has_term( 'green', 'color' ); ``` When the current post has the term ‘green’ from taxonomy ‘color’. ```php has_term( array( 'green', 'orange', 'blue' ), 'color' ); ``` When the current post has any of the terms in the array. See also [is\_archive()](https://developer.wordpress.org/reference/functions/is_archive/ "Function Reference/is archive"). ### A Registered Taxonomy [taxonomy\_exists()](https://developer.wordpress.org/reference/functions/taxonomy_exists/ "Function Reference/taxonomy exists") When a particular taxonomy is registered via [register\_taxonomy()](https://developer.wordpress.org/reference/functions/register_taxonomy/ "Function Reference/Register Taxonomy"). Formerly [is\_taxonomy()](https://developer.wordpress.org/reference/functions/is_taxonomy/) , which was deprecated in Version 3.0 ### An Author Page [is\_author()](https://developer.wordpress.org/reference/functions/is_author/ "Function Reference/is author") When any Author page is being displayed. ```php is_author( '4' ); ``` When the archive page for Author number (ID) 4 is being displayed. ```php is_author( 'Vivian' ); ``` When the archive page for the Author with Nickname “Vivian” is being displayed. ```php is_author( 'john-jones' ); ``` When the archive page for the Author with Nicename “john-jones” is being displayed. ```php is_author( array( 4, 'john-jones', 'Vivian' ) ); ``` When the archive page for the author is either user ID 4, or user\_nicename “john-jones”, or nickname “Vivian”. See also [is\_archive()](https://developer.wordpress.org/reference/functions/is_archive/ "Function Reference/is archive") and [Author Templates](https://make.wordpress.org/docs/theme-developer-handbook/part-one-theme-basics/template-hierarchy/#author-display). ### A Multi-author Site [is\_multi\_author()](https://developer.wordpress.org/reference/functions/is_multi_author/ "Function Reference/is multi author") When more than one author has published posts for a site. Available with Version 3.2. ### A Date Page [is\_date()](https://developer.wordpress.org/reference/functions/is_date/ "Function Reference/is date") When any date-based archive page is being displayed (i.e. a monthly, yearly, daily or time-based archive). [is\_year()](https://developer.wordpress.org/reference/functions/is_year/ "Function Reference/is year") When a yearly archive is being displayed. [is\_month()](https://developer.wordpress.org/reference/functions/is_month/ "Function Reference/is month") When a monthly archive is being displayed. [is\_day()](https://developer.wordpress.org/reference/functions/is_day/ "Function Reference/is day") When a daily archive is being displayed. [is\_time()](https://developer.wordpress.org/reference/functions/is_time/ "Function Reference/is time") When an hourly, “minutely”, or “secondly” archive is being displayed. [is\_new\_day()](https://developer.wordpress.org/reference/functions/is_new_day/ "Function Reference/is new day") If today is a new day according to post date. Should be used inside the loop. ### Any Archive Page [is\_archive()](https://developer.wordpress.org/reference/functions/is_archive/ "Function Reference/is archive") When any type of Archive page is being displayed. Category, Tag, Author and Date based pages are all types of Archives. ### A Search Result Page [is\_search()](https://developer.wordpress.org/reference/functions/is_search/ "Function Reference/is search") When a search result page archive is being displayed. ### A 404 Not Found Page [is\_404()](https://developer.wordpress.org/reference/functions/is_404/ "Function Reference/is 404") When a page displays after an “HTTP 404: Not Found” error occurs. ### A Privacy Policy Page [is\_privacy\_policy()](https://developer.wordpress.org/reference/functions/is_privacy_policy/) When the Privacy Policy page is being displayed. ### An Attachment [is\_attachment()](https://developer.wordpress.org/reference/functions/is_attachment/ "Function Reference/is attachment") When an attachment document to a post or Page is being displayed. An attachment is an image or other file uploaded through the post editor’s upload utility. Attachments can be displayed on their own ‘page’ or template. ### A Single Page, Single Post or Attachment [is\_singular()](https://developer.wordpress.org/reference/functions/is_singular/ "Function Reference/is singular") When any of the following return true: `is_single()`, `is_page()` or `is_attachment()`. ```php is_singular( 'book' ); ``` True when viewing a post of the Custom Post Types book. ```php is_singular( array( 'newspaper', 'book' ) ); ``` True when viewing a post of the Custom Post Types newspaper or book. ### A Syndication [is\_feed()](https://developer.wordpress.org/reference/functions/is_feed/ "Function Reference/is feed") When the site requested is a Syndication. This tag is not typically used by users; it is used internally by WordPress and is available for Plugin Developers. ### A Trackback [is\_trackback()](https://developer.wordpress.org/reference/functions/is_trackback/ "Function Reference/is trackback") When the site requested is WordPress’ hook into its Trackback engine. This tag is not typically used by users; it is used internally by WordPress and is available for Plugin Developers. ### A Preview [is\_preview()](https://developer.wordpress.org/reference/functions/is_preview/ "Function Reference/is preview") When a single post being displayed is viewed in Draft mode. ### Has An Excerpt [has\_excerpt()](https://developer.wordpress.org/reference/functions/has_excerpt/ "Function Reference/has excerpt") When the current post has an excerpt **has\_excerpt( 42 )** When the post 42 (ID) has an excerpt. ```php post_excerpt ) ) { // This post has no excerpt } else { // This post has excerpt } ``` **Other use** When you need to hide the auto displayed excerpt and only display your post’s excerpts. ```php is_single()` to display something specific only when viewing a single post page: ```php is_main_query() && is_post_type_archive( 'products' ) && ! is_admin() ) { // If it's the main query on a custom post type archive for Products. // And if we're not in the WordPress admin, then do something special. } if ( is_post_type_archive( 'movies' ) || is_tax( 'genre' ) || is_tax( 'actor' ) ) { // If it's a custom post type archive for Movies. // Or it's a taxonomy archive for Genre. // Or it's a taxonomy archive for Actor, do something special. } ``` ### Date Based Differences If someone browses our site by date, let’s distinguish posts in different years by using different colors: ```php

by '; } else { echo '
'; } } else { echo '
'; } the_content( 'Read the rest of this entry »' ); echo '
'; ?> ``` ### Variable Sidebar Content This example will display different content in your sidebar based on what page the reader is currently viewing. ```php
``` ### Helpful 404 Page The [Creating an Error 404 Page](https://codex.wordpress.org/Creating_an_Error_404_Page) article as an example of using the PHP conditional function `isset()` in the [Writing Friendly Messages](https://codex.wordpress.org/Creating_an_Error_404_Page#Writing_Friendly_Messages) section. ### In the theme’s footer.php file At times queries performed in other templates such as sidebar.php may corrupt certain conditional tags. For instance, in header.php a conditional tag works properly but doesn’t work in a theme’s footer.php. The trick is to put wp\_reset\_query before the conditional test in the footer. For example: ```php [List of Conditional Tags](https://developer.wordpress.org/themes/references/list-of-conditional-tags/) ## Function Reference [Reference](https://developer.wordpress.org/?s=is_) --- # Custom Headers Source: https://developer.wordpress.org/themes/functionality/custom-headers/ ## Custom Header [Custom headers](https://developer.wordpress.org/themes/functionality/custom-headers/) allow site owners to upload their own “title” image to their site, which can be placed at the top of certain pages. These can be customized and cropped by the user through a visual editor in the **Appearance > Header** section of the admin panel. You may also place text beneath or on top of the header. To support fluid layouts and responsive design, these headers may also be flexible. Headers are placed into a theme using `get_custom_header()`, but they must first be added to your *functions.php* file using `add_theme_support()`. Custom headers are **optional.** To set up a basic, flexible, custom header with text you would include the following code: ```php get_template_directory_uri() . 'img/default-image.jpg', 'default-text-color' => '000', 'width' => 1000, 'height' => 250, 'flex-width' => true, 'flex-height' => true, ); add_theme_support( 'custom-header', $args ); } add_action( 'after_setup_theme', 'themename_custom_header_setup' ); ``` *The [`after_setup_theme`](https://developer.wordpress.org/reference/hooks/after_setup_theme/) hook is used so that custom headers are registered after the theme is loaded.* ### What are Custom Headers? When you enable Custom Headers in your theme, users can change their header image using the WordPress theme Customizer. This gives users more control and flexibility over the look of their site. ## Add Custom Header Support to your Theme To enable Custom Headers in your theme, add the following to your *`functions.php`* file: ```php add_theme_support( 'custom-header' ); ``` When enabling Custom Headers, you can configure several other options by passing along arguments to the `add_theme_support()` function. You can pass specific configuration options to the `add_theme_support` function using an array: ```php get_template_directory_uri() . '/images/headers/default.jpg', // Display the header text along with the image. 'header-text' => false, // Header text color default. 'default-text-color' => '000', // Header image width (in pixels). 'width' => 1000, // Header image height (in pixels). 'height' => 198, // Header image random rotation default. 'random-default' => false, // Enable upload of image file in admin. 'uploads' => false, // Function to be called in theme head section. 'wp-head-callback' => 'wphead_cb', // Function to be called in preview page head section. 'admin-head-callback' => 'adminhead_cb', // Function to produce preview markup in the admin screen. 'admin-preview-callback' => 'adminpreview_cb', ); } add_action( 'after_setup_theme', 'themename_custom_header_setup' ); ``` ### Flexible Header Image If flex-height or flex-width are not included in the array, height and width will be fixed sizes. If flex-height and flex-width are included, height and width will be used as suggested dimensions instead. ### Header text By default, the user will have the option of whether or not to display header text over the image. There is no option to force the header text on the user, but if you want to remove the header text completely, you can set ‘header-text’ to ‘false’ in the arguments. This will remove the header text and the option to toggle it. ## Examples ### Set a custom header image When the user first installs your theme, you can include a default header that will be selected before they choose their own header. This allows users to set up your theme more quickly and use your default image until they’re ready to upload their own. Set a default header image 980px width and 60px height: ```php 980, 'height' => 60, 'default-image' => get_template_directory_uri() . '/images/sunset.jpg', ); add_theme_support( 'custom-header', $header_info ); $header_images = array( 'sunset' => array( 'url' => get_template_directory_uri() . '/images/sunset.jpg', 'thumbnail_url' => get_template_directory_uri() . '/images/sunset_thumbnail.jpg', 'description' => 'Sunset', ), 'flower' => array( 'url' => get_template_directory_uri() . '/images/flower.jpg', 'thumbnail_url' => get_template_directory_uri() . '/images/flower_thumbnail.jpg', 'description' => 'Flower', ), ); register_default_headers( $header_images ); ``` ![](https://i0.wp.com/developer.wordpress.org/files/2014/10/custom_headers_example1.jpg?resize=393%2C712&ssl=1)Do not forget to call [register\_default\_headers()](https://developer.wordpress.org/reference/functions/register_default_headers/) to register a default image. In this example, `sunset.jpg` is the default image and `flower.jpg` is an alternative selection in Customizer. From Administration Screen, Click **Appearance > Header** to display Header Image menu in Customizer. Notice that width and height specified in [add\_theme\_support()](https://developer.wordpress.org/reference/functions/add_theme_support/) is displayed as recommended size, and `flower.jpg` is shown as selectable option. ### Use flexible headers By default, the user will have to crop any images they upload to fit in the width and height you specify. However, you can let users upload images of any height and width by specifying ‘flex-width’ and ‘flex-height’ as true. This will let the user skip the cropping step when they upload a new photo. Set flexible headers: ```php true, 'width' => 980, 'flex-height' => true, 'height' => 200, 'default-image' => get_template_directory_uri() . '/images/header.jpg', ); add_theme_support( 'custom-header', $args ); ``` update your `header.php` file to: ```php ``` ### Displaying Custom Header To display the custom header, function [get\_header\_image()](https://developer.wordpress.org/reference/functions/get_header_image/) retrieves the header image. [get\_custom\_header()](https://developer.wordpress.org/reference/functions/get_custom_header/) gets the custom header data. E.g. below shows how custom header images can be used to display the header in the theme. The below code goes into header.php file. ```php
<?php echo esc_attr( get_bloginfo( 'name', 'display' ) ); ?>
``` ### Backwards Compatibility Custom Headers are supported in WordPress 3.4 and above. If you’d like your theme to support WordPress installations that are older than 3.4, you can use the following code instead of `add_theme_support( ‘custom-header’);` ```php =' ) ) : add_theme_support( 'custom-header' ); else : add_custom_image_header( $wp_head_callback, $admin_head_callback ); endif; ``` ## Function Reference - [header\_image()](https://developer.wordpress.org/reference/functions/header_image/) Display header image URL. - [get\_header\_image()](https://developer.wordpress.org/reference/functions/get_header_image/) Retrieve header image for custom header. - [get\_custom\_header()](https://developer.wordpress.org/reference/functions/get_custom_header/) Get the header image data. - [get\_random\_header\_image()](https://developer.wordpress.org/reference/functions/get_random_header_image/) Retrieve header image for custom header. - [add\_theme\_support()](https://developer.wordpress.org/reference/functions/add_theme_support/) Registers theme support for a given feature. - [register\_default\_headers()](https://developer.wordpress.org/reference/functions/register_default_headers/) Registers a selection of default headers to be displayed by the Customizer. --- # Sidebars Source: https://developer.wordpress.org/themes/functionality/sidebars/ ## What are Sidebars A sidebar is any widgetized area of your theme. Widget areas are places in your theme where users can add their own widgets. You do not need to include a sidebar in your theme, but including a sidebar means users can add content to the widget areas through the Customizer or the Widgets Admin Panel. Widgets can be employed for a variety of purposes, ranging from listing recent posts to conducting live chats. The name “sidebars” comes from a time when widget areas were normally created in a long strip to the lefthand or righthand side of a blog. Today, sidebars have evolved beyond their original name. They can be included anywhere on your website. Think of a sidebar as **any area that contains widgets**. ## Registering a Sidebar To use sidebars, you must register them in `functions.php`. To begin, `register_sidebar()` has several parameters that should always be defined regardless of whether they are marked as optional. These include x, y, and z. - **name** – your name for the sidebar. This is the name users will see in the Widgets panel. - **id** – must be lowercase. You will call this in your theme using the `dynamic_sidebar` function. - **description** – A description of the sidebar. This will also be shown in the admin Widgets panel. - **class** – The CSS class name to assign to the widget’s HTML. - **before\_widget** – HTML that is placed before every widget. - **after\_widget** – HTML that is placed after every widget. Should be used to close tags from `before_widget`. - **before\_title** – HTML that is placed before the title of each widget, such as a header tag. - **after\_title** – HTML that is placed after every title. Should be used to close tags from `before_title`. To register a sidebar we use `register_sidebar` and the `widgets_init` function. ```php __( 'Primary Sidebar', 'theme_name' ), 'id' => 'sidebar-1', 'before_widget' => '
', 'after_widget' => '
', 'before_title' => '

', 'after_title' => '

', ) ); register_sidebar( array( 'name' => __( 'Secondary Sidebar', 'theme_name' ), 'id' => 'sidebar-2', 'before_widget' => '
  • ', 'after_widget' => '
', 'before_title' => '

', 'after_title' => '

', ) ); } ``` Registering a sidebar tells WordPress that you’re creating a new widget area in **Appearance > Widgets** that users can drag their widgets to. There are two functions for registering sidebars: - [register\_sidebar()](https://developer.wordpress.org/reference/functions/register_sidebar/) - [register\_sidebars()](https://developer.wordpress.org/reference/functions/register_sidebars/) The first lets you register one sidebar and the second lets you register multiple sidebars. It is recommended that you register sidebars individually as it allows you to give unique and descriptive names to each sidebar. ## Examples For widget areas in header and footer, it makes sense to name them “Header Widget Area” and “Footer Widget Area”, rather than “Sidebar 1” and “Sidebar 2” (which is the default). This provides a useful description of where the sidebar is located. The following code, added to `functions.php` registers a sidebar: ```php 'primary', 'name' => __( 'Primary Sidebar' ), 'description' => __( 'A short description of the sidebar.' ), 'before_widget' => '
', 'after_widget' => '
', 'before_title' => '

', 'after_title' => '

', ) ); /* Repeat register_sidebar() code for additional sidebars. */ } ``` The code does the following: - `register_sidebar` – tells WordPress that you’re registering a sidebar - `'name' => __( 'Primary Widget Area', 'mytheme' ),` – is the widget area’s name that will appear in Appearance > Widgets - `'id' => 'sidebar-1'` – assigns an ID to the sidebar. WordPress uses ‘id’ to assign widgets to a specific sidebar. - `before_widget`/`after_widget` – a wrapper element for widgets assigned to the sidebar. The “%1$s” and “%2$s” should always be left in `id` and `class` respectively so that plugins can make use of them. By default, WordPress sets these as list items but in the above example they have been altered to div. - `before_title`/`after_title` – the wrapper elements for the widget’s title. By default, WordPress sets it to h2 but using h3 makes it more semantic. Once your sidebar is registered, you can display it in your theme. ## Displaying Sidebars in your Theme Now that your sidebars are registered, you will want to display them in your theme. To do this, there are two steps: 1. Create the `sidebar.php` template file and display the sidebar using the `dynamic_sidebar` function 2. Load in your theme using the `get_sidebar` function ### Create a Sidebar Template File A sidebar template contains the code for your sidebar. WordPress recognizes the file `sidebar.php` and any template file with the name `sidebar-{name}.php`. This means that you can organize your files with each sidebar in its own template file. ### Example: 1\. Create `sidebar-primary.php` 2\. Add the following code: ```php
``` Note that `dynamic_sidebar` takes a single parameter of `$index`, which can be either the sidebar’s name or id. ### Load your Sidebar To load your sidebar in your theme, use the `get_sidebar` function. This should be inserted into the template file where you want the sidebar to display. To load the default `sidebar.php` use the following: ```php ``` To display the Primary sidebar, pass the `$name` parameter to the function: ```php ``` ## Customizing your Sidebar There are lots of ways that you can customize your sidebars. Here are some examples: ### Display Default Sidebar Content You may wish to display content if the user hasn’t added any widgets to the sidebar yet. To do this, you use the `is_sidebar_active()` function to check to see if the sidebar has any widgets. This accepts the `$index` parameter which should be the ID of the sidebar that you wish to check. This code checks to see if the sidebar is active, if not it displays some content: ```php
``` ### Display Default Widgets You may want your sidebar to be populated with some widgets by default. For example, display the Search, Archive, and Meta Widgets. To do this you would use: ```php

    'monthly' ) ); ?>

``` --- # Widgets Source: https://developer.wordpress.org/themes/functionality/widgets/ A widget adds content and features to a widget area (also called a [sidebar](https://developer.wordpress.org/themes/functionality/sidebars/ "Sidebars")). Widget areas provide a way for users to customize their site. A widget area can appear on multiple pages or on only one page. Your theme might have just one widget area or many of them. Some examples of ways you can use widget areas are: - Lay out a homepage using widgets. This allows site owners to decide what should appear in each section of their homepage. - Create a footer that users can customize with their own content. - Add a customizable sidebar to a blog. A widget is a PHP object that outputs some HTML. The same kind of widget can be used multiple times on the same page (e.g. the Text Widget). Widgets can save data in the database (in the options table). When you create a new kind of widget, it will appear in the user’s Administration Screens at **Appearance > Widgets**. The user can add the widget to a widget area and customize the widget settings from the WordPress admin. ## Built-in versus stand-alone widgets A set of widgets is included with the default WordPress installation. In addition to these standard widgets, extra widgets can be included by themes or plugins. An advantage of widgets built into themes or plugins is to provide extra features and increase the number of widgets. A disadvantage is that if a theme is changed or a plugin is deactivated, the plugin or theme widget’s functionality will be lost. However, the data and preferences from the widget will be saved to the options table and restored if the theme or plugin is reactivated. If you include a widget with your theme, it can only be used if that theme is active. If the user decides to change their theme they will lose access to that widget. However, if the widget is included with a plugin, the user can change their theme without losing access to the widget functionality. ## Anatomy of a Widget Visually, a widget comprises two areas: 1. Title Area 2. Widget Options For example, here is the layout of the built-in text widget in the admin and on the front-end: ![Sample Editable Widget](https://i0.wp.com/make.wordpress.org/docs/files/2013/06/widget_visual.png?ssl=1)A widget form in the admin area.![A widget as it appars to a site visitor.](https://i0.wp.com/make.wordpress.org/docs/files/2013/06/Widget-front-end.png?ssl=1)A widget as it appears to a site visitor.HTML output for this widget looks like this: ```php

This is a text widget

I can put HTML in here. Search me!
``` Each widget has its own way of outputting HTML that is relevant to the data being displayed. The wrapper tags for the widget are defined by the widget area in which it is being displayed. The PHP code necessary to create a widget like the built-in text widget looks like this: ```php '

', 'after_title' => '

', 'before_widget' => '
', 'after_widget' => '
', ); public function widget( $args, $instance ) { echo $args['before_widget']; if ( ! empty( $instance['title'] ) ) { echo $args['before_title'] . apply_filters( 'widget_title', $instance['title'] ) . $args['after_title']; } echo '
'; echo esc_html__( $instance['text'], 'text_domain' ); echo '
'; echo $args['after_widget']; } public function form( $instance ) { $title = ! empty( $instance['title'] ) ? $instance['title'] : esc_html__( '', 'text_domain' ); $text = ! empty( $instance['text'] ) ? $instance['text'] : esc_html__( '', 'text_domain' ); ?>

construct`: Set up your widget with a description, name, and display width in your admin. 2. `widget`: Process the widget options and display the HTML on your page. The `$args` parameter provides the HTML you can use to display the widget title class and widget content class. 3. `form`: Display the form that will be used to set the options for your widget. If your widget doesn’t have any options, you can skip this function (although it is still best practice to include it even if it’s empty). 4. `update`: Save the widget options to the database. If your widget doesn’t have any options, you can skip this function (although it is still best practice to include it even if it’s empty). ### Registering a Widget The [register\_widget()](https://developer.wordpress.org/reference/functions/register_widget/) function is used to register a widget. Call this function using the widgets\_init hook: ```php widgets_init` action to register your widget. Next you will declare the arguments you will use when creating your widget. There are four arguments you must define, `before_title`, `after_title`, `before_widget`, and `after_widget`. These arguments will define the code that wraps your widgets title and the widget itself. After defining your arguments, you will define the widgets function. This function takes two parameters, the `$args` array from before, and the `$instance` of the widget, and is the function that will process options from the form and display the HTML for the widget on the front-end of your site. In the example above the widget function simply outputs the widget title, while passing it through the `widget_title` filter. It then out puts a simple widget wrapper and the content of the widget’s text field. As outlined in the example, you can access the options from the widget that are stored in the `$instance`. Next you will define the form function. This function takes one parameter, `$instance`, and outputs the form that the user uses to create the widget in the Widgets admin screen. In the example above, the function starts by defining the `$title` and `$text` variables and setting them to the previously entered values, if those values exist. Then it outputs a simple form with a text field for the title and a textarea for the text content. Lastly you will define the update function. This function takes two parameters, `$new_instance` and `$old_instance`, and is responsible for updating your widgets with new options when they are submitted. Here you simply define `$instance` as an empty array. You then set the title and text keys to the `$new_instance` values if they exist. You then return `$instance`. Finally, when all of the above is defined, you instantiate your new widget class and test your work. ### Sample Widget ```php __( 'A Foo Widget', 'text_domain' ) ) // Args ); } /** * Front-end display of widget. * * @see WP_Widget::widget() * * @param array $args Widget arguments. * @param array $instance Saved values from database. */ public function widget( $args, $instance ) { extract( $args ); $title = apply_filters( 'widget_title', $instance['title'] ); echo $before_widget; if ( ! empty( $title ) ) { echo $before_title . $title . $after_title; } echo __( 'Hello, World!', 'text_domain' ); echo $after_widget; } /** * Back-end widget form. * * @see WP_Widget::form() * * @param array $instance Previously saved values from database. */ public function form( $instance ) { if ( isset( $instance['title'] ) ) { $title = $instance['title']; } else { $title = __( 'New title', 'text_domain' ); } ?>

the_widget()` to display it programmatically. The function accepts widget class names. You pass the widget class name to the function like this: ```php
``` You may want to use this approach if you need to use a widget in a specific area on a page, such as displaying a list of events next to a form in a section on the front page of your site or displaying an email capture form on a mega-menu alongside your navigation. --- # Navigation Menus Source: https://developer.wordpress.org/themes/functionality/navigation-menus/ Navigation Menus are customizable menus in your theme. They allow users to add Pages, Posts, Categories, and URLs to the menu. To create a navigation menu you’ll need to register it, and then display the menu in the appropriate location in your theme. ## Register Menus In your theme’s functions.php, you need to register your menu(s). This sets the name that will appear at **Appearance -> Menus**. First of all, you will use [register\_nav\_menus()](https://developer.wordpress.org/reference/functions/register_nav_menus/) to register the menu. In this example, two locations are added to the “Manage Locations” tab: “Header Menu” and “Extra Menu”. ```php function register_my_menus() { register_nav_menus( array( 'header-menu' => __( 'Header Menu' ), 'extra-menu' => __( 'Extra Menu' ) ) ); } add_action( 'init', 'register_my_menus' ); ``` ## Display Menus Once you’ve registered your menus, you need to use [wp\_nav\_menu()](https://developer.wordpress.org/reference/functions/wp_nav_menu/) to tell your theme where to display them. For example, add the following code to your `header.php` file to display the header-menu that was registered above. ```php wp_nav_menu( array( 'theme_location' => 'header-menu' ) ); ``` A full list of parameters can be found in the [wp\_nav\_menu()](https://developer.wordpress.org/reference/functions/wp_nav_menu/) page in the function reference Repeat this process for any additional menus you want to display in your theme. Optionally, you can add a container class which allows you to style the menu with CSS. ```php wp_nav_menu( array( 'theme_location' => 'extra-menu', 'container_class' => 'my_extra_menu_class' ) ); ``` A full list of CSS Classes can be found in the [wp\_nav\_menu()](https://developer.wordpress.org/reference/functions/wp_nav_menu/) page in the function reference. You can use these to style your menus. ## Display Additional Contents Below is a simplified version of the Twenty Seventeen footer social menu, which displays `span` elements before and after the menu item label text. ```php wp_nav_menu( array( 'menu' => 'primary', 'link_before' => '', 'link_after' => '', ) ); ``` The output will display as… \[html\] <div class="menu-social-container"> <ul id="menu-social"> <li id="menu-item-1"> <a href="http://twitter.com/"><span class="screen-reader-text">Twitter</span> </li> </ul> </div> \[/html\] To display text between the `
  • ` and `` elements for each menu item, use `before` and `after` parameters. ## Define Callback By default, WordPress displays the first non-empty menu when the specified menu or location is not found, or generates a Page menu when there is no custom menu selected. To prevent this, use the `theme_location` and `fallback_cb` parameters. ```php wp_nav_menu( array( 'menu' => 'primary', // do not fall back to first non-empty menu 'theme_location' => '__no_such_location', // do not fall back to wp_page_menu() 'fallback_cb' => false ) ); ``` --- # Post Types Source: https://developer.wordpress.org/themes/basics/post-types/ There are many different types of content in WordPress. These content types are normally described as Post Types, which may be a little confusing since it refers to all different types of content in WordPress. For example, a post is a specific Post Type, and so is a page. Internally, all of the Post Types are stored in the same place — in the wp\_posts database table — but are differentiated by a database column called post\_type. In addition to the default Post Types, you can also create Custom Post Types. The [Template files](https://developer.wordpress.org/themes/basics/template-files/) page briefly mentioned that different Post Types are displayed by different Template files. As the whole purpose of a Template file is to display content a certain way, the Post Types purpose is to categorize what type of content you are dealing with. Generally speaking, certain Post Types are tied to certain template files. ## Default Post Types There are several default Post Types readily available to users or internally used by the WordPress installation. The most common are: - Post (Post Type: ‘post’) - Page (Post Type: ‘page’) - Attachment (Post Type: ‘attachment’) - Revision (Post Type: ‘revision’) - Navigation menu (Post Type: ‘nav\_menu\_item’) - Block templates (Post Type: ‘wp\_template’) - Template parts (Post Type: ‘wp\_template\_part’) The Post Types above can be modified and removed by a plugin or theme, but it’s not recommended that you remove built-in functionality for a widely-distributed theme or plugin. It’s out of the scope of this handbook to explain other post types in detail. However, it is important to note that you will interact with and build the functionality of [navigation menus](https://developer.wordpress.org/themes/functionality/navigation-menus/) and that will be detailed later in this handbook. ### Post Posts are used in blogs. They are: - displayed in reverse sequential order by time, with the newest post first - have a date and time stamp - may have the default [taxonomies of categories and tags](https://developer.wordpress.org/themes/functionality/categories-tags-custom-taxonomies/) applied - are used for creating feeds The template files that display the Post post type are: - `singl`e and `single-post` - `category` and all its iterations - `tag` and all its iterations - `taxonomy` and all its iterations - `archive` and all its iterations - `author` and all its iterations - `date` and all its iterations - `search` - `home` - `index` [Read more about Post Template Files in classic themes](https://developer.wordpress.org/themes/template-files-section/post-template-files/). ### Page Pages are a static Post Type, outside of the normal blog stream/feed. Their features are: - non-time dependent and without a time stamp - are not organized using the categories and/or tags taxonomies - can be organized in a hierarchical structure — i.e. pages can be parents/children of other pages The template files that display the Page post type are: - `page` and all its iterations - `front-page` - `search` - `index` [Read more about Page Template Files in classic themes](https://developer.wordpress.org/themes/template-files-section/page-template-files/). ### Attachment Attachments are commonly used to display images or media in content, and may also be used to link to relevant files. Their features are: - contain information (such as name or description) about files uploaded through the media upload system - for images, this includes metadata information stored in the wp\_postmeta table (including size, thumbnails, location, etc) The template files that display the Attachment post type are: - `MIME_type` - `attachment` - `single-attachment` - `single` - `index` [Read more about Attachment Template Files in classic themes](https://developer.wordpress.org/themes/template-files-section/attachment-template-files/). ## Custom Post Types Using Custom Post Types, you can **create your own post type**. It is not recommend that you place this functionality in your theme. This type of functionality should be placed/created in a plugin. This ensures the portability of your user’s content, and that if the theme is changed the content stored in the Custom Post Types won’t disappear. You can learn more about [creating custom post types in the WordPress Plugin Developer Handbook](https://developer.wordpress.org/plugins/post-types/registering-custom-post-types/). While you generally won’t develop Custom Post Types in your theme, you may want to code ways to display Custom Post Types that were created by a plugin. The following templates can display Custom post types: - `single-{post-type}` - `archive-{post-type}` - `search` - `index` [Read more about Custom Post Type Templates in classic themes](https://developer.wordpress.org/themes/template-files-section/custom-post-type-template-files/). --- # Taxonomy Templates Source: https://developer.wordpress.org/themes/template-files-section/taxonomy-templates/ When a visitor clicks on a hyperlink to category, tag or custom taxonomy, WordPress displays a page of posts in reverse chronological order filtered by that taxonomy. By default, this page is generated using the *index.php* template file. You can create optional template files to override and refine the *index.php* template files. This section explains how to use and create such templates. ## Taxonomy Template Hierarchy WordPress display posts in the order determined by the [Template Hierarchy](https://developer.wordpress.org/themes/basics/template-hierarchy/ "Template Hierarchy"). The *category.php*, *tag.php*, and *taxonomy.php* templates allow posts **filtered** by taxonomy to be treated differently from **unfiltered** posts or posts **filtered by a different taxonomy**. (Note: post refers to any post type – posts, pages, custom post types, etc.). These files let you target specific taxonomies or specific taxonomy terms. For example: - *taxonomy-{taxonomy}-{term}.php* - *taxonomy-{taxonomy}.php* - *tag-{slug}.php* - *tag-{id}.php* - *category-{slug}.php* - *category-{ID}.php* So you could format all posts in an animal taxonomy named *news* on a page that looks different from posts filtered in other categories. The *archive.php* template provides the most general form of control, providing a layout for all archives; that is, a page that displays a list of posts. ### Category For categories, WordPress looks for the *category-{slug}.php* file. If it doesn’t exist, WordPress then looks for a file for the next hierarchical level, *category-{ID}.php*, and so on. If WordPress fails to find any specialized templates or an *archive.php* template file, it reverts to the default behavior, using *index.php*. The category hierarchy is listed below: 1. *category-{slug}.php*: For example, if the category’s slug is named “news,” WordPress would look for a file named *category-news.php.* 2. *category-{ID}.php*: For example, if the category’s ID is “6”, WordPress would look for a file named *category-6.php.* 3. *category.php* 4. *archive.php* 5. *index.php* ### Tag For tags, WordPress looks for the *tag-{slug}.php* file. If it doesn’t exist, WordPress then looks for a file for the next hierarchical level, *tag-{ID}.php*, and so on. If WordPress fails to find any specialized templates or an *archive.php* template file, it will revert to the default behavior, using *index.php*. The tag hierarchy is listed below: 1. *tag-{slug}.php*: For example, if the tag’s slug is named “sometag,” WordPress would look for a file named *tag-sometag.php.* 2. *tag-{id}.php*: For example, if the tag’s ID were “6,” WordPress would look for a file named *tag-6.php*. 3. *tag.php* 4. *archive.php* 5. *index.php* ### Custom Taxonomy A custom taxonomy hierarchy works similarly to the categories and tags hierarchies described above. WordPress looks for the *taxonomy-{taxonomy}-{term}.php* file. If it doesn’t exist, WordPress then looks for a file for the next hierarchical level, *taxonomy-{taxonomy}.php*, and so on. If WordPress fails to find any specialized templates or an *archive.php* template file, it will revert to the default behavior, using *index.php*. The hierarchy for a custom taxonomy is listed below: 1. *taxonomy-{taxonomy}-{term}.php*: For example, if the taxonomy is named “sometax,” and the taxonomy’s term is “someterm,” WordPress would look for a file named *taxonomy-sometax-someterm.php*. 2. *taxonomy-{taxonomy}.php*: For example, if the taxonomy is named “sometax,” WordPress would look for a file named *taxonomy-sometax.php* 3. *taxonomy.php* 4. *archive.php* 5. *index.php* ## Creating Taxonomy Template Files Now you’ve decided that you need to create custom designs for content based on taxonomies, where do you start? Rather than starting from a blank file, it is good practice to **copy the next file in the hierarchy**, if it exists. If you’ve already created an *archive.php*, make a copy called *category.php* and modify that to suit your design needs. If you don’t have an *archive.php* file, use a copy of your theme’s *index.php* as a starting point. Follow the same procedure if you are creating any taxonomy template file. Use a copy of your *archive.php*, *category.php*, *tag.php*, or *index.php* as a starting point. ## Examples Now that you’ve selected the template file in your theme’s directory that you need to modify, let’s look at some examples. ### Adding Text to Category Pages #### Static Text Above Posts Suppose you want some static text displayed before the list of posts on your category page(s). “Static” is text that remains the same, no matter which posts are displayed below, and no matter which category is displayed. Open your file and above [The Loop](https://developer.wordpress.org/themes/basics/the-loop/ "The Loop") section of your Template file, insert the following code: ```markup

    This is some text that will display at the top of the Category page.

    ``` This text will only display on an archive page displaying posts in that category. #### Different Text on Some Category Pages What if you want to display different text based on the category page that the visitor is using? You could add default text to the main *category.php* file, and create special *category-{slug}.php* files each with their own version of the text, but this would create lots of files in your theme. Instead, you can use [conditional tags](https://developer.wordpress.org/themes/basics/conditional-tags/ "Conditional Tags"). Again, this code would be added before the loop: ```php

    This is the text to describe category A.

    This is the text to describe category B.

    This is some generic text to describe all other category pages, I could be left blank.

    ``` This code does the following: 1. Checks to see if the visitor has requested Category A. If yes, it displays the first piece of text. 2. Checks for category B if the user didn’t request category A. If yes, it displays the second piece of text. 3. Displays the default text, if neither was requested. #### Display Text only on First Page of Archive If you have more posts than fits on one page of your archive, the category splits into multiple pages. Perhaps you want to display static text, if the user is on the first page of the results. To do this, use a PHP if statement that looks at the value of the $paged WordPress variable. Put the following above The Loop: ```php

    Text for first page of Category archive.

    ``` This code asks whether the page displayed is the first page of the archive. If it is, the text for the first page is displayed. Otherwise, the text for the subsequent pages is displayed. ### Modify How Posts are Displayed #### Excerpts vs. Full Posts You can choose whether to display full posts or just excerpts. By displaying excerpts, you shorten the length of your archive page. Open your file and find the loop. Look for: ```php the_content() ``` And replace it with: ```php the_excerpt() ``` And if your theme is displaying excerpts but you want to display the full content, replace `the_excerpt` with `the_content`. --- # Categories, Tags, & Custom Taxonomies Source: https://developer.wordpress.org/themes/basics/categories-tags-custom-taxonomies/ Categories, tags, and taxonomies are all related and can be easily confused. We’ll use the example of building a theme for a recipe website to help break down categories, tags, and taxonomies. In our recipe website, the **categories** would be Breakfast, Lunch, Dinner, Appetizers, Soups, Salads, Sides, and Desserts. All recipes will fit within those categories, but users might want to search for something specific like chocolate desserts or ginger chicken dinners. Chocolate, ginger, and chicken are all examples of **tags**. They are another level of specificity that provides meaning to the user. Lastly, there are taxonomies. In reality, categories and tags are examples of default taxonomies which simply are a way to organize content. Taxonomies are the method of classifying content and data in WordPress. When you use a taxonomy you’re grouping similar things together. The taxonomy refers to the sum of those groups. As with Post Types, there are a number of default taxonomies, and you can also create your own. Recipes are normally organized by category and tag, but there are some other helpful ways to break the recipes down to be more user friendly. For example, the recipe website might want an easy way to display recipes by cook time. A custom taxonomy of cook time with 0-30 min, 30-min to an hour, 1 to 2 hours, 2+ hours would be a great breakdown. Additionally, cook method such as grill, oven, stove, refrigerator, etc would be another example of a custom taxonomy that would be relevant for the site. There could also be a custom taxonomy for how spicy the recipe is and then a rating from 1-5 on spiciness. ## Default Taxonomies The default taxonomies in WordPress are: - categories: a hierarchical taxonomy that organizes content in the *post* Post Type - tags: a non-hierarchical taxonomy that organizes content in the *post* Post Type - post formats: a method for creating formats for your posts. You can learn more about these on the [Post Formats](https://developer.wordpress.org/themes/functionality/post-formats/ "Post Formats") page. ### Terms Terms are items within your taxonomy. So, for example, if you have the *Animal* taxonomy you would have the terms, dogs, cats, and sheep. Terms can be created via the WordPress admin, or you can use the [wp\_insert\_term()](https://developer.wordpress.org/reference/functions/wp_insert_term/ "wp_insert_term") function. ## Database Schema Taxonomies and terms are stored in the following database tables: - wp\_terms – stores all of the terms - wp\_term\_taxonomy – places the term in a taxonomy - wp\_term\_relationships – relates the taxonomy to an object (for example, *category* to *post)* [![taxonomy-schema](https://i0.wp.com/developer.wordpress.org/files/2014/10/taxonomy-schema.png?resize=311%2C452&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2014/10/taxonomy-schema.png?ssl=1)## Templates WordPress offers several different hierarchies of templates for categories, tags, or custom taxonomies. More details on their structure and usage may be found on the [Taxonomy Templates](https://developer.wordpress.org/themes/functionality/taxonomy-templates/ "Taxonomy Templates") page. ## Custom Taxonomies It is possible to create new taxonomies in WordPress. You may, for example, want to create an *author* taxonomy on a book review website, or an *actor* taxonomy on a film site. As with custom post type **it is recommended that you put this functionality in a plugin**. This ensures that when the user changes their website’s design, their content is preserved in the plugin. You can read more about creating custom taxonomies in the [Plugin Developer Handbook.](https://developer.wordpress.org/plugins/taxonomy/working-with-custom-taxonomies/ "Working with Custom Taxonomies") --- # Pagination Source: https://developer.wordpress.org/themes/functionality/pagination/ Pagination allows your user to *page* back and forth through multiple pages of content. WordPress can use pagination when: - Viewing lists of posts when more posts exist than can fit on one page, or - Breaking up longer posts by manually by using the following tag: `` ## Using Pagination to Navigate Post Lists The most common use for pagination in WordPress sites is to break up long lists of posts into separate pages. Whether you’re viewing a category, archive, or default index page for a blog or site, WordPress only shows 10 posts per page by default. Users can change the number of posts that appear on each page on the Reading screen: **Admin > Settings > Reading**. ## Examples ### Loop with Pagination This simplified example shows where you can add pagination functions for the main loop. Add the functions just before or after the loop. ```php
    ``` ### Methods for displaying pagination links When using any of these pagination functions outside the template file with the loop that is being paginated, you must call the global variable $wp_query. ```php function your_themes_pagination() { global $wp_query; echo paginate_links(); } ``` WordPress has numerous functions for displaying links to other pages in your loop. Some of these functions are only used in very specific contexts. You would use a different function on a single post page then you would on a archive page. The following section covers archive template pagination functions. The section after that cover single post pagination. #### Simple Pagination **posts\_nav\_link** One of the simplest methods is [posts\_nav\_link()](https://developer.wordpress.org/reference/functions/posts_nav_link/). Simply place the function in your template after your loop. This generates both links to the next page of posts and previous page of posts where applicable. This function is ideal for themes that have simple pagination requirements. ```php posts_nav_link(); ``` **next\_posts\_link & prev\_posts\_link** When building a theme, use [next\_posts\_link()](https://developer.wordpress.org/reference/functions/next_posts_link/) and [prev\_posts\_link()](https://developer.wordpress.org/reference/functions/previous_posts_link/). to have control over where the previous and next posts page link appears. ```php next_posts_link(); previous_posts_link(); ``` If you need to pass the pagination links to a PHP variable, you can use [get\_next\_posts\_link()](https://developer.wordpress.org/reference/functions/get_next_posts_link/) and [get\_previous\_posts\_link()](https://developer.wordpress.org/reference/functions/get_previous_posts_link/). ```php $next_posts = get_next_posts_link(); $prev_posts = get_previous_posts_link(); ``` #### Numerical Pagination When you have many pages of content it is a better experience to display a list of page numbers so the user can click on any one of the page links rather then having to repeatedly click next or previous posts. WordPress provides several functions for automatically displaying a numerical pagination list. **For WordPress 4.1+** If you want more robust pagination options, you can use [the\_posts\_pagination()](https://developer.wordpress.org/reference/functions/the_posts_pagination/) for WordPress 4.1 and higher. This will output a set of page numbers with links to previous and next pages of posts. ```php the_posts_pagination(); ``` **For WordPress prior to 4.1** If you want your pagination to support older versions of WordPress, you must use [paginate\_links()](https://developer.wordpress.org/reference/functions/paginate_links/). ```php echo paginate_links(); ``` #### Pagination Between Single Posts All of the previous functions should be used on index and archive pages. When you are viewing a single blog post, you must use [prev\_post\_link](https://developer.wordpress.org/reference/functions/previous_post_link/) and [next\_post\_link](https://developer.wordpress.org/reference/functions/next_post_link/). Place the following functions below the loop on your single.php. ```php previous_post_link(); next_post_link(); ``` ### Pagination within a post WordPress gives you a tag that can be placed in post content to enable pagination for that post: `\` If you use that tag in the content, you need to ensure that the [wp\_link\_pages](https://developer.wordpress.org/reference/functions/wp_link_pages/) function is placed in your single.php template within the loop. ```php ``` --- # Comment Template Source: https://developer.wordpress.org/themes/template-files-section/partial-and-miscellaneous-template-files/comment-template/ WordPress displays comments in your theme based on the settings and code in the `comments.php` file within your WordPress theme. ## Simple comments loop ```php // Get only the approved comments $args = array( 'status' => 'approve', ); // The comment Query $comments_query = new WP_Comment_Query(); $comments = $comments_query->query( $args ); // Comment Loop if ( $comments ) { foreach ( $comments as $comment ) { echo '

    ' . $comment->comment_content . '

    '; } } else { echo 'No comments found.'; } ``` The `comments.php` template contains all the logic needed to pull comments out of the database and display them in your theme. Before we explore the template file you’ll want to know how to pull in the partial template file on the appropriate pages such as `single.php`. You’ll wrap the comment [template tag](https://developer.wordpress.org/themes/basics/template-tags/) in a conditional statement so comments.php is only pulled in if it makes sense to do. ```php // If comments are open or we have at least one comment, load up the comment template. if ( comments_open() || get_comments_number() ) : comments_template(); endif; ``` ![functionality-comments-01](https://i0.wp.com/developer.wordpress.org/files/2014/10/functionality-comments-01.png?resize=350%2C257&ssl=1)## Another comments.php Example Here’s an example of the `comments.php` template included with the Twenty Thirteen theme: ```php

    ' . get_the_title() . '' ); ?>

      'ol', 'short_ping' => true, 'avatar_size' => 74, ) ); ?>
    1 && get_option( 'page_comments' ) ) : ?>

    ``` ## Breaking down the comments.php The above `comments.php` can be broken down to the below parts for better understanding. 1. [Template Header](#template-header) 2. [Comments Title](#comments-title) 3. [Comment Listing](#comment-listing) 4. [Comment Pagination](#comment-pagination) 5. [Comments are closed message](#comments-are-closed-message). 6. [The End](#the-end) ### Template Header This template begins by identifying the template. ```php ``` Finally, there’s a test to see if there are comments associated with this post. ```php
    ``` ### Comments Title Prints out the header that appears above the comments. Uses the [\_nx()](https://developer.wordpress.org/reference/functions/_nx/) translation function so other developers can provide alternative language translations. ```php

    ' . get_the_title() . '' ); ?>

    ``` ### Comment Listing The following snippet creates an ordered listing of comments using the [wp\_list\_comments()](https://developer.wordpress.org/reference/functions/wp_list_comments/) function. ```php
      'ol', 'short_ping' => true, 'avatar_size' => 74, ) ); ?>
    ``` ### Comment Pagination Checks to see if there are enough comments to merit adding comment navigation and, if so, create comment navigation. ```php 1 && get_option( 'page_comments' ) ) : ?>

    ``` ### Comments are closed message. If comments aren’t open, displays a line indicating that they’re closed. ```php

    ``` ### The End This section ends the comments loop, includes the comment form, and closes the comment wrapper. ```php
    ``` ## Comments Pagination If you have a lot of comments (which makes your page long), then there are a number of potential benefits to paginating your comments. Pagination helps improve page load speed, especially on mobile devices. Enabling comments pagination is done in two steps. 1. Enable paged comments within WordPress by going to *Settings* > *Discussion* , and checking the box “*Break comments into pages*” . You can enter any number for the “*top level comments per page*”. 2. Open your `comments.php` template file and add the following line where you want the comment pagination to appear. ```php
    ``` ## Alternative Comment Template On some occasions you may want display your comments differently within your theme. For this you would build an alternate file (ex. short-comments.php) and call it as follows: ```php get_posts()
    ` or `get_children()` function. This example retrieves the all attachments of the current post and getting all metadata of attachment by specifying the ID. ```php // Insert into the Loop $args = array(     'post_parent'    => get_the_ID(),     'post_type'      => 'attachment', ); $attachments = get_posts( $args ); if ( $attachments ) {     foreach ( $attachments as $attachment ) {         $meta_data = wp_get_attachment_metadata( $attachment->ID, false );     } } ``` If you want to retrieve images from the post ID only, specify post\_mime\_type as image. ```php $args = array(     'post_parent'    => get_the_ID(),     'post_type'      => 'attachment',     'post_mime_type' => 'image', ); ``` #### References - `get_posts()` - `get_children()` - `wp_get_attachment_metadata()` ## Special considerations ### Compatible media formats In the Media Library, you can upload any file (with the network administrator’s unfiltered\_upload) and not just images or videos but text files, office documents or even binary files. Single site administrators do not have the unfiltered\_upload capability by default and requires that definition to be set for the capability to kick in. Audio and Video files are processed by the internal library `MediaElement.js`. - [Supported Audio format](https://developer.wordpress.org/?post_type=theme-handbook&p=25145#supported-audio-format) - [Supported Video format](https://developer.wordpress.org/themes/functionality/media/video/#supported-video-format) ### Troubleshooting: #### Cannot retrieve attachment When you cannot get your attached media by `get_posts()` or `get_children()` function, confirm your media is really attached to the post. From the [Administration Screen](https://codex.wordpress.org/Administration_Screens), Click **Media > Library** to open the Media Library and confirm the value in “Uploaded to” column of the media. --- # Featured Images & Post Thumbnails Source: https://developer.wordpress.org/themes/functionality/featured-images-post-thumbnails/ Featured images (also sometimes called Post Thumbnails) are images that represent an individual Post, Page, or Custom Post Type. When you create your Theme, you can output the featured image in a number of different ways, on your archive page, in your header, or above a post, for example. ## Enabling Support for Featured Image Themes must declare support for the Featured Image function before the Featured Image interface will appear on the Edit screen. Support is declared by putting the following in your theme’s [functions.php](https://make.wordpress.org/docs/theme-developer-handbook/theme-basics/theme-functions/ "Theme Functions") file: ```php add_theme_support( 'post-thumbnails' ); ``` To enable Featured Image only for specific post types, see [add\_theme\_support()](https://developer.wordpress.org/reference/functions/add_theme_support/ "Allows a theme to register its support of a certain feature...") ## Setting a Featured Image Once you add support for Featured Images, the Featured Image meta box will be visible on the appropriate content item’s Edit screens. If a user is unable to see it, they can enable it in their screen options. By default, the Featured Image meta box is displayed in the sidebar of the Edit Post and Edit Page screens. [![devhbook-featured_image](https://i0.wp.com/make.wordpress.org/docs/files/2013/02/devhbook-featured_image1.png?ssl=1)](https://i0.wp.com/make.wordpress.org/docs/files/2013/02/devhbook-featured_image1.png?ssl=1)## Function Reference `add_image_size()` – Register a new image size. `set_post_thumbnail_size()` – Registers an image size for the post thumbnail. `has_post_thumbnail()` – Check if post has an image attached. `the_post_thumbnail()` – Display Post Thumbnail. `get_the_post_thumbnail()` – Retrieve Post Thumbnail. `get_post_thumbnail_id()` – Retrieve Post Thumbnail ID. ## Image Sizes The default image sizes of WordPress are “Thumbnail”, “Medium”, “Large” and “Full Size” (the original size of the image you uploaded). These image sizes can be configured in the WordPress Administration Media panel under **>Settings > Media**. You can also define your own image size by passing an array with your image dimensions: ```php the_post_thumbnail(); // Without parameter ->; Thumbnail the_post_thumbnail( 'thumbnail' ); // Thumbnail (default 150px x 150px max) the_post_thumbnail( 'medium' ); // Medium resolution (default 300px x 300px max) the_post_thumbnail( 'medium_large' ); // Medium-large resolution (default 768px x no height limit max) the_post_thumbnail( 'large' ); // Large resolution (default 1024px x 1024px max) the_post_thumbnail( 'full' ); // Original image resolution (unmodified) the_post_thumbnail( array( 100, 100 ) ); // Other resolutions (height, width) ``` ## Add Custom Featured Image Sizes In addition to defining image sizes individually using ```php the_post_thumbnail( array( , ) ); ``` you can create custom featured image sizes in your theme’s functions file that can then be called in your theme’s template files. ```php add_image_size( 'category-thumb', 300, 9999 ); // 300 pixels wide (and unlimited height) ``` Here is an example of how to create custom Featured Image sizes in your theme’s `functions.php` file. ```php if ( function_exists( 'add_theme_support' ) ) { add_theme_support( 'post-thumbnails' ); set_post_thumbnail_size( 150, 150, true ); // default Featured Image dimensions (cropped) // additional image sizes // delete the next line if you do not need additional image sizes add_image_size( 'category-thumb', 300, 9999 ); // 300 pixels wide (and unlimited height) } ``` ## Set the Featured Image Output Size To be used in the current Theme’s functions.php file. You can use `set_post_thumbnail_size()` to set the default Featured Image size by resizing the image proportionally (that is, without distorting it): ```php set_post_thumbnail_size( 50, 50 ); // 50 pixels wide by 50 pixels tall, resize mode ``` Set the default Featured Image size by cropping the image (either from the sides, or from the top and bottom): ```php set_post_thumbnail_size( 50, 50, true ); // 50 pixels wide by 50 pixels tall, crop mode ``` ## Styling Featured Images Featured Images are given a class “wp-post-image”. They also get a class depending on the size of the thumbnail being displayed. You can style the output with these CSS selectors: ```css img.wp-post-image img.attachment-thumbnail img.attachment-medium img.attachment-large img.attachment-full ``` You can also give Featured Images their own classes by using the attribute parameter in [the\_post\_thumbnail()](https://developer.wordpress.org/reference/functions/the_post_thumbnail/ "Display Post Thumbnail"). Display the Featured Image with a class “alignleft”: ```php the_post_thumbnail( 'thumbnail', array( 'class' => 'alignleft' ) ); ``` ## Examples ### Default Usage ```php // check if the post or page has a Featured Image assigned to it. if ( has_post_thumbnail() ) { the_post_thumbnail(); } ``` To return the Featured Image for use in your PHP code instead of displaying it, use: [get\_the\_post\_thumbnail()](https://developer.wordpress.org/reference/functions/get_the_post_thumbnail/ "Retrieve Post Thumbnail") ```php // check for a Featured Image and then assign it to a PHP variable for later use if ( has_post_thumbnail() ) { $featured_image = get_the_post_thumbnail(); } ``` ### Linking to Post Permalink or Larger Image Don’t use these two examples together in the same Theme. Example 1. To link Post Thumbnails to the Post Permalink in a specific loop, use the following within your Theme’s template files: ```php ``` Example 2. To link **all Post Thumbnails** on your website to the Post Permalink, put this in the current Theme’s [functions.php](https://make.wordpress.org/docs/theme-developer-handbook/part-one-theme-basics/theme-functions/ "Theme Functions") file: ```php add_filter( 'post_thumbnail_html', 'my_post_image_html', 10, 3 ); function my_post_image_html( $html, $post_id, $post_image_id ) { $html = '' . $html . ''; return $html; } ``` This example links to the “large” Post Thumbnail image size and must be used within The Loop. ```php if ( has_post_thumbnail()) { $large_image_url = wp_get_attachment_image_src( get_post_thumbnail_id(), 'large'); echo ''; the_post_thumbnail('thumbnail'); echo ''; } ``` ## Source File - [wp-includes/post-thumbnail-template.php](https://core.trac.wordpress.org/browser/tags/3.5.1/wp-includes/post-thumbnail-template.php#L0) ## External Resources - [Everything you need to know about WordPress 2.9’s post image feature](http://justintadlock.com/archives/2009/11/16/everything-you-need-to-know-about-wordpress-2-9s-post-image-feature) - [The Ultimative Guide For the\_post\_thumbnail In WordPress 2.9](http://wpengineer.com/the-ultimative-guide-for-the_post_thumbnail-in-wordpress-2-9/) - [New in WordPress 2.9: Post Thumbnail Images](http://markjaquith.wordpress.com/2009/12/23/new-in-wordpress-2-9-post-thumbnail-images/) --- # Post Formats Source: https://developer.wordpress.org/themes/functionality/post-formats/ A Post Format is used by a theme for presenting posts in a certain format and style. The Post Formats feature provides a standardized list of formats available to all themes that support the feature. A theme may not support every format on the list; in such a case, it is good form to make this known to users. A theme cannot introduce formats not on the standardized list, even through plugins. This standardization ensures compatibility between themes and a way for external tools to use the feature in a consistent fashion. In short, with a theme that supports Post Formats, a blogger can change how a post looks by choosing a Post Format. Using **Asides** as an example, in the past, a category called Asides was created, and posts were assigned that category, and then displayed differently based on styling rules from [post\_class()](https://developer.wordpress.org/reference/functions/post_class/) or from [in\_category(‘asides’)](https://developer.wordpress.org/reference/functions/in_category/). With **Post Formats**, the new approach allows a theme to add support for a Post Format (e.g. [add\_theme\_support(‘post-formats’, array(‘aside’))](https://developer.wordpress.org/reference/functions/add_theme_support/)), and then the post format can be selected in the Publish meta box when saving the post. A function call of [get\_post\_format($post->ID)](https://developer.wordpress.org/reference/functions/get_post_format/) can be used to determine the format, and [post\_class()](https://developer.wordpress.org/reference/functions/post_class/) will also create the “format-asides” class, for pure-css styling. ## Supported Formats The following Post Formats are available, if supported by the theme. Note that while actual post content won’t change, the theme can display a post differently based on the format chosen. How posts are displayed is entirely up to the theme, but here are some general guidelines on typical uses for the different Post Formats. - **aside** – Typically styled without a title. Similar to a Facebook note update. - **gallery** – A gallery of images. Post will likely contain a gallery shortcode and will have image attachments. - **link** – A link to another site. Themes may wish to use the first <a href=””> tag in the post content as the external link for that post. An alternative approach could be if the post consists only of a URL, then that will be the URL and the title (post\_title) will be the name attached to the anchor for it. - **image** – A single image. The first <img /> tag in the post could be considered the image. Alternatively, if the post consists only of a URL, that will be the image URL and the title of the post (post\_title) will be the title attribute for the image. - **quote** – A quotation. Probably will contain a blockquote holding the quote content. Alternatively, the quote may be just the content, with the source/author being the title. - **status** – A short status update, similar to a Twitter status update. - **video** – A single video. The first <video /> tag or object/embed in the post content could be considered the video. Alternatively, if the post consists only of a URL, that will be the video URL. May also contain the video as an attachment to the post, if video support is enabled on the blog (like via a plugin). - **audio** – An audio file. Could be used for Podcasting. - **chat** – A chat transcript, like so: ```bash John: foo Mary: bar John: foo 2 ``` When writing or editing a Post, “Standard” designates that no Post Format is specified. Also if an invalid format is specified, “Standard” (no format) is applied by default. ## Function Reference ### Main Functions - [set\_post\_format()](https://developer.wordpress.org/reference/functions/set_post_format/) - [get\_post\_format()](https://developer.wordpress.org/reference/functions/get_post_format/) - [has\_post\_format()](https://developer.wordpress.org/reference/functions/has_post_format/) ### Other Functions - [get\_post\_format\_link()](https://developer.wordpress.org/reference/functions/get_post_format_link/) - [get\_post\_format\_string()](https://developer.wordpress.org/reference/functions/get_post_format_string/) ## Adding Theme Support Themes need to use [add\_theme\_support()](https://developer.wordpress.org/reference/functions/add_theme_support/) in the *functions.php* file to tell WordPress which post formats to support by passing an array of formats like so: ```php array( 'title', 'editor', 'author', 'post-formats' ), ); register_post_type( 'book', $args ); ``` [add\_post\_type\_support](https://developer.wordpress.org/reference/functions/add_post_type_support/) should be hooked to [init](https://developer.wordpress.org/reference/hooks/init/) hook, as custom post types may not have been registered at [after\_setup\_theme](https://developer.wordpress.org/reference/hooks/after_setup_theme/). ## Using Formats In the theme, use [get\_post\_format()](https://developer.wordpress.org/reference/functions/get_post_format/) to check the format for a post, and change its presentation accordingly. Note that posts with the default format will return a value of FALSE. Alternatively, use the [has\_post\_format()](https://developer.wordpress.org/reference/functions/has_post_format/) [conditional tag](https://developer.wordpress.org/themes/basics/conditional-tags/): ```php Settings Page ``` By passing the string through a localization function it can it can be easily parsed to be translated. ```php

    ``` WordPress uses [gettext](http://www.gnu.org/software/gettext/) libraries to be able to add the translations in PHP. In WordPress you should use the WordPress localization functions instead of the native PHP gettext-compliant translation functions. ### Text Domain The text domain is the second argument that is used in the internationalization functions. The text domain is a unique identifier, allowing WordPress to distinguish between all of the loaded translations. The text domain is only needed to be defined for themes and plugins. Themes that are hosted on WordPress.org the text domain must match the slug of your theme URL (`wordpress.org/themes/`). This is needed so that the translations from [translate.wordpress.org](https://translate.wordpress.org/) work correctly. The text domain name must use dashes and not underscores and be lowercase. For example, if the theme’s name `My Theme` is defined in the `style.css` or it is contained in a folder called `my-theme` the text domain should be `my-theme`. The text domain is used in three different places: 1. In the `style.css` theme header 2. As an argument in the localization functions 3. As an argument when loading the translations using `load_theme_textdomain()` or `load_child_theme_textdomain()` #### style.css theme header The text domain is added to the `style.css` header so that the theme meta-data like the description can be translated even when the theme is not enabled. The text domain should be same as the one used when [loading the text domain](#loading-text-domain). **Example:** ```php /* * Theme Name: My Theme * Author: Theme Author * Text Domain: my-theme */ ``` ##### Domain Path The domain path is needed when the translations are saved in a directory other than `languages` . This is so that WordPress knows where to find the translation when the theme is not activated. For example, if .mo files are located in the languages folder then Domain Path will be `/languages` and must be written with the first slash. Defaults to the `languages` folder in the theme. **Example:** ```php /* * Theme Name: My Theme * Author: Theme Author * Text Domain: my-theme * Domain Path: /languages */ ``` #### Add text domain to strings The text domain should be added as an argument to all of the localization functions for the translations to work correctly. **Example 1**: ```php __( 'Post' ) ``` should become ```php __( 'Post', 'my-theme' ) ``` **Example 2**: ```php _e( 'Post' ) ``` should become ```php _e( 'Post', 'my-theme' ) ``` **Example 3**: ```php _n( '%s post', '%s posts', $count ) ``` should become ```php _n( '%s post', '%s posts', $count, 'my-theme' ) ``` The text domain should be passed as a string to the localization functions instead of a variable. It allows parsing tools to differentiate between text domains. Example of what not to do: ```php __( 'Translate me.' , $text_domain ); ``` #### Loading Translations The translations in WordPress are saved in `.po` and `.mo` files which need to be loaded. They can be loaded by using the functions `load_theme_textdomain()` or `load_child_theme_textdomain()`. This loads `{locale}.mo` from your theme’s base directory or `{text-domain}-{locale}.mo` from the WordPress theme language folder in `/wp-content/languages/themes/`. As of version 4.6 WordPress automatically checks the language directory in `wp-content` for translations from [translate.wordpress.org](https://translate.wordpress.org/). This means that plugins that are translated via translate.wordpress.org do not require `load_plugin_textdomain()` anymore. If you don’t want to add a `load_plugin_textdomain()` call to your plugin you should set the `Requires at least:` field in your readme.txt to 4.6. To find out more about the different language and country codes, see [the list of languages](https://make.wordpress.org/polyglots/teams/ "https://codex.wordpress.org/WordPress_in_Your_Language"). **Watch Out** - Name your MO file as `{locale}.mo` (e.g. de\_DE.po & de\_DE.mo) if adding the translation to the theme folder. - Name your MO file as `{text-domain}-{locale}.mo` (e.g my-theme-de\_DE.po & my-theme-de\_DE.mo) if you are adding the translation to the WordPress theme language folder. **Example:** ```php function my_theme_load_theme_textdomain() { load_theme_textdomain( 'my-theme', get_template_directory() . '/languages' ); } add_action( 'after_setup_theme', 'my_theme_load_theme_textdomain' ); ``` This function should ideally be run within the theme’s `function.php`. ##### Language Packs If you’re interested in language packs and how the import to [translate.wordpress.org](https://translate.wordpress.org/) is working, please read the [Meta Handbook page about Translations](https://make.wordpress.org/meta/handbook/documentation/translations/). ## Internationalizing your theme Now that your translations are loaded, you can start writing every string in your theme with Internationalization functions. Check the [Internationalization](https://developer.wordpress.org/apis/handbook/internationalization/) page on the [Common APIs Handbook](https://developer.wordpress.org/apis/) for more information and best practices. --- # Localization Source: https://developer.wordpress.org/themes/functionality/localization/ ## What is localization? Localization describes the subsequent process of translating an internationalized theme. Localization is abbreviated as `l10n` (because there are 10 letters between the l and the n.) Please refer to the [Localization](https://developer.wordpress.org/apis/handbook/internationalization/localization/) page on the [Common APIs handbook](https://developer.wordpress.org/apis/) to learn how to Localize your theme. --- # Accessibility Source: https://developer.wordpress.org/themes/functionality/accessibility/ A WordPress theme should generate pages everyone can use, including those who cannot see or use a mouse. To create an accessible theme, you need to have knowledge of web standards for HTML, CSS, and JavaScript. You also need to be aware of best practices for web accessibility and have basic knowledge of the [Web Content Accessibility Guidelines](https://www.w3.org/WAI/WCAG21/quickref/), WCAG. To succeed in making your theme accessible, accessibility should be considered from the start of your project as part of your project specification. By making the right decisions from the beginning, you can avoid making last-minute adjustments that can be costly, time-consuming, and of low quality. The [Accessibility Team](https://make.wordpress.org/accessibility/) have documented many of the best practices and resources for development, design, and content in their handbook. In the handbook, you can also learn about testing for accessibility. The [Themes Team](https://make.wordpress.org/themes/) has two sets of accessibility requirements for themes submitted to the WordPress.org theme directory: - [Requirements for all themes](https://make.wordpress.org/themes/handbook/review/required/#3-accessibility) - [Requirements for using the “‘accessibility-ready” tag](https://make.wordpress.org/themes/handbook/review/accessibility/) The accessibility-ready requirements are based on WCAG but adapted for WordPress themes. “Accessibility Ready” does **not** mean that the theme meets the WCAG guidelines [AA-level](https://make.wordpress.org/accessibility/handbook/make/which-questions-should-you-ask/#levels-of-accessibility). It means that the theme reaches the minimum standards that the theme review team has set. ## The four principles of web accessibility Although web accessibility can be a complex subject, it boils down to only four principles. The content must be: ### Perceivable Content must be available to all. It should not depend on a specific device or browser or require a specific physical sense, such as sight or sound. ### Operable Users must be able to move around and operate the final site effectively, whether they’re using a keyboard, a mouse, or assistive technology. ### Understandable The content should be presented in a manner that supports understanding, including supporting the construction of a mental model of the site for screen reader users. Similarly, the site’s operation (navigation menus, links, forms, etc.) should be easily understandable. Building a theme that incorporates known user behaviors (such as underlining links within the main content area) helps in this respect. ### Robust Content must be equally available across a wide range of user agents. Disabled users may employ a range of hardware and software solutions (commonly referred to as “assistive technology”) to allow them to access the Web—including screen reading & voice recognition software, braille readers, and switches (single input devices). A theme designed with these four principles in mind eases the creation of an accessible website. --- ## Perceivable and understandable ### Color and color contrast Having a high enough color contrast between background and foreground colors makes content easier to read. Theme authors must ensure that all background/foreground color contrasts for plain content text are within the level AA contrast ratio (4.5:1) specified in the Web Content Accessibility Guidelines (WCAG) 2.0 for color luminosity. - Color may not be the only way to identify controls, links in text content, or error messages. - If there is no text decoration on linked text, there must be a 3:1 color contrast between the link text color and the surrounding non-link text color, in addition to the other color contrast requirements. There are separate requirements for links in content (links surrounded by other text) and links that are grouped together in navigation menus. Groups of links do not need to be underlined if it is obvious from the context that they are links. [Best practices for the use of color](https://make.wordpress.org/accessibility/handbook/design/use-of-color/) [Accessibility-ready requirements for contrast](https://make.wordpress.org/themes/handbook/review/accessibility/required/#contrasts) ### Resizable text Users have many means to resize text, including browser settings. All content and functionality must remain available if the user resizes the text up to 200% of the original size. - Resizing text must not trigger multi-dimensional scrolling - Enlarged texts must not cause overflows or overlaps To avoid these issues, it is recommended to: - Use a relative unit for font sizes and line heights - Test your theme in different browsers and screen widths [Best practices for font sizes and resized text](https://make.wordpress.org/accessibility/handbook/design/font-sizes-and-resize-text/) ### Images #### Non-decorative images Example: - A header image that replaces header text - Images used in place of text for navigation Non-decorative images included with `img` elements should have an `alt` attribute. #### Decorative images Example: - A header image used alongside header text - Images and icons accompanying navigation text links When possible, decorative images should be included using CSS. - Decorative images included with `img` elements should have an empty `alt` attribute: `alt=""`. - Decorative images that are displayed together with text should be hidden from screen readers using `aria-hidden`. #### Featured images The alt attribute for featured images is defined in the media library. - If the featured image is unlinked, the alt attribute should describe the image - If the featured image is linked to a post, the alt text should use the post title [Best practices for alt texts](https://make.wordpress.org/accessibility/handbook/content/alternative-text-for-images/) [Accessibility-ready requirement for images](https://make.wordpress.org/themes/handbook/review/accessibility/required/#images) ## Operable ### Controls All controls must be usable with the keyboard on all screen sizes, including but not limited to buttons for opening and closing menus, submenus, any type of dialog, modal, and popup. [Best practices for dialog modals](https://make.wordpress.org/accessibility/handbook/markup/dialog-modal/) [Accessibility-ready requirements for controls](https://make.wordpress.org/themes/handbook/review/accessibility/required/#controls) ### Headings Headings are an essential way of breaking content down into logical sub-sections. Heading levels indicate the importance of the content. Screen reader users can scan the contents of a page by reading the headings, and navigating to a section via its heading. That is why it is important that headings are used logically and not for presentational purposes. [Best practices for Heading structure in theme development](https://make.wordpress.org/accessibility/handbook/markup/heading-structure-in-theme-development/) [Accessibility-ready requirements for headings](https://make.wordpress.org/themes/handbook/review/accessibility/required/#headings) ### Links #### Link text Link text should describe the resource that it links to, even when the text is read out of context. Some assistive software scans a page for links and presents them to the user as a simple list. In these situations, all the links will be read out of context. So it is important the text used in a link is descriptive. Bare URLs should never be used as links. [Good link texts](https://make.wordpress.org/accessibility/handbook/content/good-link-texts/) [Accessibility-ready requirements: Avoiding repetitive Read More or Continue reading texts.](https://make.wordpress.org/themes/handbook/review/accessibility/required/#repetitive-link-text) #### Link underlining and styling link states Generally speaking, links should be underlined if they are outside navigation menus and lists. Using color alone to distinguish links is insufficient as not everyone can perceive color. Users must be able to tell if a text is linked if they are hovering over a link, if they are focusing on a link, and if they have already visited a link. The default browser style for the focus state should not be removed unless replaced with a more visible focus style. [Accessibility-ready requirements for underlining links in the content](https://make.wordpress.org/themes/handbook/review/accessibility/required/#content-links) #### Skip Links Skip links provide a mechanism that enables users to navigate directly to content or navigation on entering any given page. For example, a skip to content link might allow a user to skip a header area and go directly to the main content. In designs with multiple menus and content areas, multiple skip links can be used: - Skip to the main navigation - Skip to content - Skip to footer These links may be positioned off-screen initially using an appropriate CSS technique but should remain available to screen reader users and be visible on focus for sighted keyboard navigators. [Best practices for Skip Links](https://make.wordpress.org/accessibility/handbook/markup/skip-links/) [Accessibility-ready requirements for Skip Links](https://make.wordpress.org/themes/handbook/review/accessibility/required/#skip-links) ### Forms - Provide enough information for the user to be able to complete the form. - All input fields must have a label. A placeholder text is not a replacement for the label. Input fields must also have a visible focus style. - Group controls that belong together, for example, a set of related checkboxes, with a `fieldset` and `legend`. - Make sure that the tab order in the form matches the visual order of the input fields: Do not move focus unexpectedly or skip past input fields. #### On Form Submission Post-submission responses—including any error messages—should always be perceivable. If possible, error messages should be generated at the top of the post-submission page so the user is immediately aware of any issues. Error messages should also make sense when read out of context. [Best practices for forms](https://make.wordpress.org/accessibility/handbook/markup/web-forms/) [Accessibility-ready requirements for forms](https://make.wordpress.org/themes/handbook/review/accessibility/required/#forms) ## Robust Use the HTML element that is the best match for the content. Use buttons when performing an action, and links when navigating to a part of a page or a new page. - The content of the website should be available even if the user disables both JavaScript and CSS - Establish which [browsers](https://make.wordpress.org/core/handbook/best-practices/browser-support/) your theme supports and test your theme with these browsers on different screen sizes ## Resources [Make WordPress Accessible](https://make.wordpress.org/accessibility/) is the official blog for the WordPress Accessibility Team, dedicated to making WordPress accessible to as many people as possible. Anyone can join in the discussions, bug scrubs, and meetings. You can also follow discussions via email or subscribe to feeds for posts and comments. - [Test for web accessibility](https://make.wordpress.org/accessibility/handbook/test-for-web-accessibility/) - [Development tools](https://make.wordpress.org/accessibility/handbook/which-tools-can-i-use/useful-tools/) - [WCAG 2 (external link)](https://www.w3.org/WAI/standards-guidelines/wcag/) Changelog: - **Rewritten and published** 2023-02-16 --- # Administration Menus Source: https://developer.wordpress.org/themes/functionality/administration-menus/ This is no longer the recommended way to work with theme options. The [Customizer API](https://developer.wordpress.org/themes/customize-api/) is the recommended way to give more control and flexibility to your users Theme authors might need to provide a settings screen, so users can customize how their theme is used or works. The best way to do this is to create an administration menu item that allows the user to access that settings screen from all the administration screens. ## Function Reference ### Menu Pages [add\_menu\_page()](https://codex.wordpress.org/Function_Reference/add_menu_page) [add\_object\_page()](https://codex.wordpress.org/Function_Reference/add_object_page) [add\_utility\_page()](https://codex.wordpress.org/Function_Reference/add_utility_page) [remove\_menu\_page()](https://codex.wordpress.org/Function_Reference/remove_menu_page) ### Sub-menu Pages [add\_submenu\_page()](https://codex.wordpress.org/Function_Reference/add_submenu_page) [remove\_submenu\_page()](https://codex.wordpress.org/Function_Reference/remove_submenu_page) ### WordPress Administration Menus [add\_dashboard\_page()](https://codex.wordpress.org/Function_Reference/add_dashboard_page) [add\_posts\_page()](https://codex.wordpress.org/Function_Reference/add_posts_page) [add\_media\_page()](https://codex.wordpress.org/Function_Reference/add_media_page) [add\_links\_page()](https://codex.wordpress.org/Function_Reference/add_links_page) [add\_pages\_page()](https://codex.wordpress.org/Function_Reference/add_pages_page) [add\_comments\_page()](https://codex.wordpress.org/Function_Reference/add_comments_page) [add\_theme\_page()](https://codex.wordpress.org/Function_Reference/add_theme_page) [add\_plugins\_page()](https://codex.wordpress.org/Function_Reference/add_plugins_page) [add\_users\_page()](https://codex.wordpress.org/Function_Reference/add_users_page) [add\_management\_page()](https://codex.wordpress.org/Function_Reference/add_management_page) [add\_options\_page()](https://codex.wordpress.org/Function_Reference/add_options_page) ## Every Plot Needs a Hook To add an administration menu, there are three things you need to do: 1. Create a function that contains the menu-building code. 2. Register the above function using the `admin_menu` action hook – or `network_admin_menu`, if you are adding a menu for the Network. 3. Create the HTML output for the screen, displayed when the menu item is clicked. Most developers overlook the second step in this list. You can’t simply call the menu code. You need to put it **inside a function**, and then register this function. Here is a simple example of these three steps described. This will add a sub-level menu item under the Settings top-level menu. When selected, that menu item will show a very basic screen. ```php '; } ``` In this example, the function `my_menu()` adds a new item to the Settings administration menu via the [`add_options_page()`](https://codex.wordpress.org/Function_Reference/add_options_page) function. *Note:* Note that the [add\_action()](https://codex.wordpress.org/Function_Reference/add_action) call in Step 2 *registers* the my\_menu() function under the [admin\_menu](https://codex.wordpress.org/Plugin_API/Action_Reference/admin_menu) hook. **Without that, [add\_action()](https://developer.wordpress.org/reference/functions/add_action/) call, a PHP error for undefined function will be thrown**. Finally, the `add_options_page()` call refers to the `my_options()` function which contains the actual page to be displayed (and PHP code to be processed) when someone clicks the menu item. These steps are described in more detail in the sections below. Remember to enclose the creation of the menu and the page in functions, and use the `admin_menu` [hook](https://codex.wordpress.org/Plugin_API/Action_Reference) to get the whole process started at the right time. ## Determining Location for New Menus Before creating a new menu, first decide if the menu should be a **top-level** menu, or a **sub-level** menu item. A top-level menu displays as new section in the administration menus and contains sub-level menu items. This means a sub-level menu item is a member of an existing top-level menu. It is rare that a theme would require the creation of a new top-level menu. If the theme introduces an entirely new concept to WordPress and needs many screens to do it, then that theme may warrant a new top-level menu. Adding a top-level menu should only be considered if you really need multiple, related screens to make WordPress do something it was not originally designed to accomplish. Examples of new top-level menus might include job management or conference management. Please note that, with the native [post type](https://codex.wordpress.org/Glossary#Post_Type) registration, WordPress automatically creates top-level menus to manage this kind of features. If the creation of a top-level menu is not necessary, you need to decide under what top-level menu to place your new sub-level menu item. As a point of reference, several themes add sub-level menu items underneath existing WordPress top-level menus. Use this guide of the WordPress top-level menus to determine the correct location for your sub-level menu item: - Dashboard – information central for your site and include the Updates option for updating WordPress core, plugins, and themes. - Posts – displays tools for writing posts (time oriented content). - Media – uploading and managing your pictures, videos, and audio. - Links – manage references to other blogs and sites of interest. - Pages – displays tools for writing your static content called pages. - Comments – controlling and regulation reader to responses to posts. - Appearance – displays controls for manipulation of theme/style files, sidebars, etc. - Plugins – displays controls dealing with plugin management, not configuration options for a plugin itself. - Users – displays controls for user management. - Tools – manage the export, import, and even backup of blog data. - Settings – displays plugin options that only administrators should view. - Network Admin – displays plugin options that are set on the Network. Instead of `admin_menu`, you should use `network_admin_menu` (see also [Create A Network](https://codex.wordpress.org/Create_A_Network)) ### Top-Level Menus If you have decided your theme requires a brand-new top-level menu, the first thing you’ll need to do is to create one with the `add_menu_page()` function. *Note:* skip to [Sub-Level Menus](#sub-level-menus) if you don’t need a top-level menu. Parameter values: - `page_title` – the text to be displayed in the title tags of the page when the menu is selected. - `menu_title` – the on-screen name text for the menu. - `capability` – the capability required for this menu to be displayed to the user. When using the Settings API to handle your form, you should use `manage_options` here as the user won’t be able to save options without it. User levels are deprecated and should not be used here. - `menu_slug` – the slug name to refer to this menu by (should be unique for this menu). Prior to Version 3.0 this was called the file (or handle) parameter. If the function parameter is omitted, the `menu_slug` should be the PHP file that handles the display of the menu page content. - `function` – the function that displays the page content for the menu page. - `icon_url` – the URL to the icon to be used for this menu. This parameter is optional. - `position` – the position in the menu order this menu should appear. By default, if this parameter is omitted, the menu will appear at the bottom of the menu structure. To see the current menu positions, use `print_r( $GLOBALS[ 'menu' ] )` after the menu has loaded. - Sub-Level Menus – once your top-level menu is defined, or you have chosen to use an existing WordPress top-level menu, you are ready to define one or more sub-level menu items using the `add_submenu_page()` function. ### Sub-Level Menus If you want your new menu item to be a sub-menu item, you can create it using the `add_submenu_page()` function instead. Parameter values: - `parent_slug` – the slug name for the parent menu, or the file name of a standard WordPress admin file that supplies the top-level menu in which you want to insert your sub-menu, or your plugin file if this sub-menu is going into a custom top-level menu. Examples: - Dashboard – `add_submenu_page('index.php', ...)` - Posts – `add_submenu_page('edit.php', ...)` - Media – `add_submenu_page('upload.php', ...)` - Links – `add_submenu_page('link-manager.php', ...)` - Pages – `add_submenu_page('edit.php?post_type=page', ...)` - Comments – `add_submenu_page('edit-comments.php', ...)` - Custom Post Types – `add_submenu_page('edit.php?post_type=your_post_type', ...)` - Appearance – `add_submenu_page('themes.php', ...)` - Plugins – `add_submenu_page('plugins.php', ...)` - Users – `add_submenu_page('users.php', ...)` - Tools – `add_submenu_page('tools.php', ...)` - Settings – `add_submenu_page('options-general.php', ...)` - `page_title` – text that will go into the HTML page title for the page when the submenu is active. - `menu_title` – the text to be displayed in the title tags of the page when the menu is selected. - `capability` – the capability required for this menu to be displayed to the user. User levels are deprecated and should not be used here. - `menu_slug` – for existing WordPress menus, the PHP file that handles the display of the menu page content. For sub-menus of a custom top-level menu, a unique identifier for this sub-menu page. - `function` – the function that displays the page content for the menu page. Technically, as in the `add_menu_page` function, the function parameter is optional, but if it is not supplied, then WordPress will basically assume that including the PHP file will generate the administration screen, without calling a function. ### Using Wrapper Functions Since most sub-level menus belong under the Settings, Tools, or Appearance menus, WordPress supplies wrapper functions that make adding a sub-level menu items to these top-level menus easier. Note that the function names may not match the names seen in the admin UI as they have changed over time: #### Dashboard ```php ' . __( 'Test Settings', 'menu-test' ) . ''; } // mt_tools_page() displays the page content for the Test Tools sub-menu. function mt_tools_page() { echo '

    ' . __( 'Test Tools', 'menu-test' ) . '

    '; } // mt_toplevel_page() displays the page content for the custom Test Top-Level menu. function mt_toplevel_page() { echo '

    ' . __( 'Test Top-Level', 'menu-test' ) . '

    '; } // mt_sublevel_page() displays the page content for the first sub-menu of the custom Test Toplevel menu. function mt_sublevel_page() { echo '

    ' . __( 'Test Sub-Level', 'menu-test' ) . '

    '; } // mt_sublevel_page2() displays the page content for the second sub-menu of the custom Test Top-Level menu. function mt_sublevel_page2() { echo '

    ' . __( 'Test Sub-Level 2', 'menu-test' ) . '

    '; } ``` ## Sample Menu Page *Note:* See the [Settings API](https://codex.wordpress.org/Settings_API) for information on creating settings pages. The previous example contains several dummy functions, such as `mt_settings_page()`, as placeholders for actual page content. Let’s expand on them. What if you wanted to create an option called `mt_favorite_color` that allows the site owner to type in their favorite color via a Settings page? The `mt_options_page()` function will need to output a data entry form on the screen, as well as to process the entered data. Here is a function that does this: ```php
    ' . __( 'Menu Test Settings', 'menu-test' ) . ''; ?>

    My Plugin is not configured yet. Please do it now.
  • '; } function my_options() { if ( ! current_user_can( 'manage_options' ) ) { wp_die( __( 'You do not have sufficient permissions to access this page.' ) ); } echo '
    '; echo 'Here is where the form would go if I actually had options.'; echo '
    '; } ``` ## Resources [Top Level Menu discussion on wp-hackers ](http://comox.textdrive.com/pipermail/wp-hackers/2009-February/024632.html)[Admin Menu Editor Plugin](https://wordpress.org/extend/plugins/admin-menu-editor/) --- # 404 Pages Source: https://developer.wordpress.org/themes/functionality/404-pages/ A 404 page is important to add into your theme in case a user stumbles upon a page that doesn’t exist or hasn’t been created yet. It is also important that your 404 page gives your visitors a way to arrive at the right place. These next few steps will help you build a useful 404 page for your WordPress theme. ## Creating the 404.php file As the `404.php` file is used on a page not found error, the first step is to create a file named `404.php` and add it to your WordPress theme folder. Often times a great starting point for your `404.php` is your `index.php` ## Add a file header To use your theme’s `header.php` file, open your `404.php` file. At the top, add a comment describing what the file is and make sure you include your theme’s header. For example: ```php /** * The template for displaying 404 pages (Not Found) */ get_header(); ``` ## Adding the body to your 404 Page To make the 404 page functional you have to add the body content to your template: Example: ```php

    ``` This example is from the Twenty Thirteen theme that comes with WordPress. This adds some text and a search form in the 404 page. You can to add your own text to make your 404 page look better. ## Adding the footer and sidebar. The final step when creating a 404 page is to add the footer. You may also add a sidebar if you want. Example: ```php get_sidebar(); get_footer(); ``` Now you have a functional 404 page with a search form and some text in case a user stumbles upon the wrong page. Once you make sure the `404.php` has been uploaded, you can test your 404 page. Just type a URL address for your website that doesn’t exist. You can try something like `http://example.com/fred.php`. This is sure to result in a 404 error unless you actually have a PHP file called `fred.php`.`` --- # Child Themes Source: https://developer.wordpress.org/themes/advanced-topics/child-themes/ Child themes are extensions of a parent theme. They allow you to modify an existing theme without directly editing that theme’s code. They are often something as simple as a few minor color changes, but they can also be complex and include custom overrides of the parent theme. In this article, you will learn what parent and child themes are, how to create your own modifications via child themes, and what pieces of a parent theme that can be overridden. ## What are parent and child themes? ### Parent themes All themes—unless they are specifically a child theme—are technically parent themes. Basically, this means that they are complete themes that can be installed and activated in WordPress. Parent themes must have all of the required files, as outlined in the [Theme Structure](https://developer.wordpress.org/themes/core-concepts/theme-structure/) documentation. Beyond that, you don’t have to do anything special for your theme to *become a parent theme.* ### Child themes A child theme includes everything from its parent theme by default. This includes the design and any of its functionality. But it can also be used to make customizations to the parent theme without directly modifying the parent theme’s files. This means that you (or your child theme’s users) can still receive updates to the parent theme without losing those modifications. Child themes: - Make your modifications portable and replicable. - Keep customizations separate from the parent theme. - Allow parent themes to be updated without losing your modifications. - Save on development time since you’re only writing the code you need. - Are a great way to start your journey toward developing full themes. It’s worth noting that making extensive customizations from within a child theme can eventually become a management headache. For these more extensive projects, it is often better to fork the original theme and create a full/parent theme of your own. This is something you will need to decide on a case-by-case basis. ### What about grandchild themes? This is not currently possible. There are only two levels to the standard theme hierarchy: parent and child theme. However, when building block themes, there are other levels to what is presented on the front end of a site (they are just not a part of the theme layer): - WordPress itself (default `theme.json`) - Parent theme - Child theme - User customizations (can override `theme.json`, templates, and patterns) In a way, the user customization layer works as a “grandchild” theme of sorts. The big difference is that the changes are stored in the database instead of the filesystem. Outside of that, there is no standard method of creating an installable grandchild theme. ## How to create a child theme Let’s try creating a child theme of the default [Twenty Twenty-Four](https://wordpress.org/themes/twentytwentyfour/) theme bundled with WordPress. ### Create a child theme folder First, your child theme needs a name. This can be whatever you want your theme to be called, but for this guide, let’s name it “Grand Sunrise.” Now create a new folder in your `wp-content/themes` directory with a kebab-case version of your theme name: `grand-sunrise`. ### Create a style.css Now you’ll need to create a file named `style.css`. It is the one absolutely necessary file for a child theme to exist. All `style.css` files must contain a File Header and the required header fields, as outlined in the [Main Stylesheet](https://developer.wordpress.org/themes/core-concepts/main-stylesheet/) documentation (please review this doc if you have not already done so). As noted in the Main Stylesheet documentation, there is an additional field necessary to declare a theme as a child theme. You must add the `Template` header field to the `style.css` File Header: ```css /** * Theme Name: Grand Sunrise * Template: twentytwentyfour * ...other header fields */ ``` There is one caveat to the `Template` field. It must be a 100% match of the folder name of the parent theme, relative to the `wp-content/themes` folder. In this case, we know that the Twenty Twenty-Four theme folder is located at `wp-content/themes/twentytwentyfour`. Therefore, the `Template` value must be `twentytwentyfour`. ### Install and activate child theme If you are not already working within a development environment with your theme in the `wp-content/themes` folder, you’ll need to move it there now. Depending on your setup, you have several options, but the easiest is to create a ZIP file of your theme and upload it to your test site via **Appearance > Themes > Add New** in your WordPress admin. For more information on how to add a theme to a WordPress, read [Adding New Themes](https://wordpress.org/documentation/article/work-with-themes/#adding-new-themes) from the WordPress Documentation site. Once your theme is installed, visit **Appearance > Themes** in your WordPress admin and locate your theme. Click the **Activate** link as shown in this screenshot: [![WordPress Appearance > Themes screen showing the popup overlay of an empty child theme.](https://i0.wp.com/developer.wordpress.org/files/2024/01/child-theme-activate.jpg?resize=2048%2C1055&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2024/01/child-theme-activate.jpg?ssl=1)It won’t look any different from your parent theme right now because you haven’t customized it yet. But you have successfully created a child theme. ## Customizing your child theme When customizing your child theme, all the functionality documented throughout this handbook is fully available to you. But there are a few considerations you should keep in mind, which you’ll learn about in the following sections. ### Loading style.css This is an optional step and often not needed for block themes because their style handling is generally done via [`theme.json`](https://developer.wordpress.org/themes/global-settings-and-styles/). But it is often necessary if you are building a classic theme. Regardless, you only need to perform this step if you want to ensure that any CSS code in `style.css` is loaded. Before proceeding with this section, be sure to review the [Including Assets](https://developer.wordpress.org/themes/core-concepts/including-assets/) documentation, which covers how to load `style.css` in more detail. In that documentation, you will learn how to enqueue stylesheets via the [`wp_enqueue_style()`](https://developer.wordpress.org/reference/functions/wp_enqueue_style/) function on the appropriate hook (note that child themes are loaded before their parent themes). The ideal method of enqueueing stylesheets is when a parent theme loads both its own `style.css` and the child theme’s `style.css`. But not all themes do this. Therefore, you must examine the code of the parent theme to see which stylesheets it is enqueueing. This is different for every theme, and there are no hard rules. If the parent theme loads both stylesheets, the child theme does not need to do anything. Its stylesheet will be automatically loaded. In the case of the Twenty Twenty-Four theme, it doesn’t load a stylesheet at all. So you would have to load your `style.css` via `functions.php` as shown in this code snippet: ```php add_action( 'wp_enqueue_scripts', 'grand_sunrise_enqueue_styles' ); function grand_sunrise_enqueue_styles() { wp_enqueue_style( 'grand-sunrise-style', get_stylesheet_uri() ); } ``` If the parent theme you are using only loads its own stylesheet, you would also use the above code to load your child theme’s `style.css`. If the parent theme loads only the active theme’s stylesheet, such as via `get_stylesheet_uri()`, then it will load the child theme’s stylesheet. In this case, you may want to also enqueue the parent theme’s stylesheet via `functions.php`, and your code would look like this: ```php add_action( 'wp_enqueue_scripts', 'grand_sunrise_enqueue_styles' ); function grand_sunrise_enqueue_styles() { wp_enqueue_style( 'grand-sunrise-parent-style', get_parent_theme_file_uri( 'style.css' ) ); } ``` ### Templates, parts, and patterns When building a child theme, you have the option to overwrite any template, part, or pattern that exists in the parent theme by adding a file of the same name in your child theme. *Note: patterns must also have the same registered `Slug` field.* You can also add brand new templates, parts, and patterns to your child theme, even if they don’t exist in the parent. To learn more about these features, refer to these articles in the handbook: - [Templates](https://developer.wordpress.org/themes/templates/) - [Patterns](https://developer.wordpress.org/themes/features/block-patterns/) ### Using functions.php Unlike templates and patterns, the `functions.php` file of a child theme does not override the `functions.php` file in the parent theme. In fact, they are both loaded, with the child being loaded immediately before the parent. In that way, the `functions.php` of a child theme provides a smart, trouble-free method of modifying the functionality of a parent theme or WordPress. Suppose that you wanted to add a PHP function to your theme. The fastest way would be to open its `functions.php` file and put the function there. But that’s not considered a good practice—**the next time your theme is updated, your function will disappear!** It’s much better to create a child theme and add your custom code to your child theme’s `functions.php` file. The function will do the exact same job from there too, with the advantage that it will not be affected by future updates of the parent theme. Do not copy code directly from the `functions.php` of a parent theme into your child theme. That will likely lead to fatal errors because of duplicate function names. To learn more about `functions.php`, check out the [Custom Functionality](https://developer.wordpress.org/themes/core-concepts/custom-functionality/) documentation. ### Referencing or including other files Sometimes you need to include or use custom files in your theme. When doing so, you need to make sure that you’re using the function that will give you the correct directory path or URI based on your child theme’s directory. For example, if you wanted to include another PHP file via your `functions.php`, you would use the [`get_theme_file_path()`](https://developer.wordpress.org/reference/functions/get_theme_file_path/) function. Here is a code snippet that shows including a `functions-helpers.php` file from an `/inc` folder in your child theme: ```php require_once get_theme_file_path( 'inc/functions-helpers.php' ); ``` To learn more about including files, read the [Custom Functionality](https://developer.wordpress.org/themes/core-concepts/custom-functionality/) documentation. When you need to reference a file by its URL, such as an image or stylesheet, you must use a different function: [`get_theme_file_uri()`](https://developer.wordpress.org/reference/functions/get_theme_file_uri/). Let’s look at an example of using a file named `bunny.jpg` from your theme’s `/assets/images` folder in an `` HTML tag: ```php ``` You can find out more about including scripts, styles, images, and other assets from the [Including Assets](https://developer.wordpress.org/themes/core-concepts/including-assets/) documentation. ### Internationalization Like parent themes, child themes can also be internationalized and made to work in any language. To learn more, read the [Internationalization](https://developer.wordpress.org/themes/advanced-topics/internationalization/) documentation in the Theme Handbook. The biggest changes, as noted in the Internationalization documentation, are that you must create a unique text domain and use [`load_child_theme_textdomain()`](https://developer.wordpress.org/reference/functions/load_child_theme_textdomain/) instead of [`load_theme_textdomain()`](https://developer.wordpress.org/reference/functions/load_theme_textdomain/) when manually loading translations. --- # Theme Options – The Customize API Source: https://developer.wordpress.org/themes/customize-api/ The Customize API (Customizer) is a framework for live-previewing any change to WordPress. It provides a unified interface for users to customize various aspects of their theme and their site, from colors and layouts to widgets, menus, and more. Themes and plugins alike can add options to the Customizer. The Customizer is the canonical way to add options to your theme. [![The customizer as it appears in WordPress 4.6 with the Twenty Fifteen theme.](https://i0.wp.com/developer.wordpress.org/files/2014/10/customize-4.6.png?resize=640%2C360&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2014/10/customize-4.6.png?ssl=1)The customizer as it appears in WordPress 4.6 with the Twenty Fifteen theme. Customizer options can be granted to users with different capabilities on a granular basis, so while most options are visible only to administrators by default, other users may access certain options if you want them to be able to. Different parts of the Customizer can also be contextual to whether they’re relevant to the front-end context that the user is previewing. For example, the core widgets functionality only shows widget areas that are displayed on the current page; other widget areas are shown when the user navigates to a page that includes them within the Customizer preview window. This section contains an overview of the Customize API, including code examples and discussion of best practices. For more details, it is strongly recommended that developers study the core customizer code (all core files containing “customize”). This is considered the canonical, official documentation for the Customize API outside of the inline documentation within the core code. --- # UI Best Practices Source: https://developer.wordpress.org/themes/advanced-topics/ui-best-practices/ ## Logo Homepage Link The logo at the top each page should send the user to the homepage of your site. If you are using the recommended function, [the\_custom\_logo()](https://developer.wordpress.org/reference/functions/the_custom_logo/) or the site logo block, the logo is linked to the homepage by default. You can also add your logo manually. Assuming your logo is in your theme directory, this is how to display it in the `header.php` template file. ```php <?php esc_attr_e( 'Home Page', 'textdmomain' );?> ``` ## Descriptive Anchor Text The anchor text is the visible text for a hyperlink. Good link text should give the reader an idea of the action that will take place when clicking it. A bad example: ``` The best way to learn WordPress is to start using it. To Download WordPress, click here. ``` A better example: ``` Download WordPress and start using it. That's the best way to learn. ``` ## Style Links with Underlines By default, browsers underline links to let the user know what is clickable. Some designers use CSS to turn off underlines for hyperlinks. This causes usability and accessibility problems, as it makes it more difficult to identify hyperlinks from the surrounding text. ## Different Link Colors Color is another visual cue that text is clickable. Styling hyperlinks with a different color than the surrounding text makes them easier to distinguish. Hyperlinks are one of the few HTML features that have state. The two most important states are *visited* and *unvisited*. Having different colors for these two states helps users identify the pages they’ve visited before. A good trick for taking the guess work out of visited links is to color them 10%-20% darker than the unvisited links. There are 3 other states that links can have: - hover, when a mouse is over an element - focus, similar to hover but for keyboard users - active, when a user is clicking on a link Since hover and focus have similar meanings, it is useful to give them the same styles. Though hover and focus have similar meanings, they have different interaction patterns. If you choose a subtle hover state, you should have a more easily identifiable focus state. Hovering over a link is a directed activity, where the user knows where they are in the page and only needs to identify whether that spot is linked. Focus is an undirected activity, where the user needs to discover where their focus has moved to after shifting focus from the previous location. ## Color Contrast Color contrast refers to the **difference between two colors**. Contrast is low between navy blue and black. Contrast is high between white and black. WebAIM, a non-profit web accessibility organization, provides a [color contrast calculator](https://webaim.org/resources/contrastchecker/) to help you determine the contrast in your website design. The WCAG 2.0 requires a ratio of 4.5:1 on normal text to be [AA compliant](http://www.w3.org/WAI/WCAG20/quickref/#qr-visual-audio-contrast-contrast). ## Sufficient Font Size Make your text easy to read. By making your text large enough, you increase the usability of your site and make the content easier to understand. 14px is the smallest text should be. ## Associate Labels with Inputs Labels inform the user what an input field is for. You can connect the label to the input by using the `for` attribute in the label. This will allow the user to click the label and focus on the input field. ``` ``` Labels work for radio buttons as well. Since it works using the **id** field *and not the name*, each input for the group gets its own label. ``` ``` ## Placeholder Text in Forms Placeholder text shows the user an example of what to type. When a user puts their cursor in the field, the placeholder text will disappear, while the label remains. ``` ``` Use placeholders to suggest the type of data a field requires, and not as a substitute for the field label. ## Descriptive Buttons The web is filled with buttons that have unclear meanings. Remember the last time you used ‘OK’ or ‘submit’ on your login form? Choosing better words to display on your buttons can make your website easier to use. Try the pattern *\[verb\] \[noun\]* — Create user, Delete File, Update Password, Send Message. Each describes what will happen when the user clicks the button. --- # JavaScript Best Practices Source: https://developer.wordpress.org/themes/advanced-topics/javascript-best-practices/ Many themes use JavaScript to provide interactivity, animation or other enhancements. These best practices will help ensure your code works efficiently and does not cause conflicts with your content or plugins. ## Use Included Libraries There are many useful JavaScript libraries you may want to include when building your theme. Did you know that WordPress comes bundled with dozens of popular libraries? Check out this [list of default scripts included with WordPress](https://developer.wordpress.org/themes/basics/including-css-javascript/#default-scripts-included-and-registered-by-wordpress). A common mistake made by beginning theme and plugin developers is to bundle their theme or plugin with their own version of the library. This may conflict with other plugins that enqueue the version bundled with WordPress. As a best practice, make your theme compatible with the version of your favorite library included with WordPress. Do not try to use your own version of a JavaScript library that is already [bundled](https://developer.wordpress.org/themes/basics/including-css-javascript/#default-scripts-included-and-registered-by-wordpress "Default Scripts Included with WordPress") with WordPress. Doing so may break core functionality and conflict with plugins. If you feel you MUST replace the WordPress version with one of your own… well… the answer is still: don’t do it. The versions of JavaScript libraries used by WordPress may include custom tweaks that WordPress needs to operate. Any time you override these libraries, you risk breaking your WordPress instance. Moreover, plugins created by other authors should be written to be compatible with WordPress’s version of these libraries as well. Adding your own version may (and often does!) conflict with plugins. ## Standard JavaScript Javascript is growing in popularity for web developers, and it’s being used to accomplish for a variety of tasks. Here are some best practices to use when writing your JavaScript - Avoid Global Variables - Keep your JavaScript unobtrusive - Use closures and the [module pattern](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) - Stick to a coding style. Use The [WordPress Javascript Coding Standard](https://make.wordpress.org/core/handbook/coding-standards/javascript/). - Validate and Lint Your Code – [E](http://JSLint.com)[S](http://JSLint.com)[Lint.com](https://eslint.org/) - Ensure your site still works without JavaScript first – then add JavaScript to provide additional capabilities. This is a form of [Progressive Enhancement](http://en.wikipedia.org/wiki/Progressive_enhancement). - Lazy load assets that aren’t immediately required. - Don’t use jQuery *if you don’t need to* — There’s a great site that shows you how to do some common tasks with plain old JavaScript – [you might not need jQuery](http://youmightnotneedjquery.com) ## jQuery ### Including jQuery in your theme [jQuery](http://www.jquery.com) is a popular JavaScript library to make working with JavaScript easier and more reliable across browsers. If you use jQuery, be sure to [follow the handbook guidelines on including JavaScript](https://developer.wordpress.org/themes/basics/including-css-javascript/). Giving your theme’s enqueued .js files a dependency array of `array( 'jquery' )` ensures that the jQuery script has been downloaded and loaded before your theme’s code. #### Using $ Because the copy of jQuery included in WordPress loads in `noConflict()` mode, use this wrapper code in your theme’s .js files to map “$” to “jQuery”: ```javascript ( function( $ ) { // Your code goes here } )( jQuery ); ``` This wrapper (called an Immediately Invoked Function Expression, or IIFE) lets you pass in a variable—jQuery—on the bottom line, and give it the name “$” internally. Within this wrapper you may use `$` to select elements as normal. ### Selectors Every time you select an element with jQuery, it performs a query through your document’s markup. These queries are very fast, but they do take time—you can make your site respond faster by re-using your jQuery objects instead of using a new query. So instead of repeating selectors: ```javascript // Anti-pattern $('.post img').addClass('theme-image'); $('.post img').on('click', function() { ... }); ``` it is recommended to **cache your selectors** so you can re-use the returned element without having to repeat the lookup process: ```javascript var $postImage = $('.post img'); // All image tags within posts can now be accessed through $postImage $postImage.addClass('theme-image'); $postImage.on('click', function() { ... }); ``` ### Event Handling When you use jQuery methods like `.bind` or `.click`, jQuery creates a new browser event object to handle processing the requested event. Each new event created takes a small amount of memory, but the amount of memory required goes up the more events you bind. If you have a page with a hundred anchor tags and wanted to fire a `logClick` event handler whenever a user clicked a link, it is very easy to write code like this: ```javascript // Anti-pattern $('a').click( logClick ); ``` This works, but under the hood you have asked jQuery to create a new event handler for every link on your page. **Event delegation** is a way to accomplish the same effect with less overhead. Because events in jQuery “bubble”—that is, a click event will fire on a link, then on the link’s surrounding `

    ` tag, then on the `div` container, and so on up to the `document` object itself—we can put a single event handler higher up in the page structure, and still catch the click events for all of those links: ```javascript // Bind one handler at the document level, which is triggered // whenever there is a "click" event originating from an "a" tag $(document).on('click', 'a', logClick); ``` --- # Plugin API Hooks Source: https://developer.wordpress.org/themes/advanced-topics/plugin-api-hooks/ A theme should work well with WordPress plugins. Plugins add functionality by using actions and filters, which are collectively called hooks (see [Plugin API](https://codex.wordpress.org/Plugin_API "Plugin API") for more information). Most hooks are executed internally by WordPress, so your theme does not need special tags for them to work. However, a few hooks need to be included in your theme templates. These hooks are fired by special Template Tags: [wp\_head()](https://developer.wordpress.org/reference/functions/wp_head/ "Function Reference/wp head")Goes at the end of the <head> element of a theme’s *header.php* template file.[wp\_body\_open()](https://developer.wordpress.org/reference/functions/wp_body_open/ "Function Reference/wp head")Goes at the begining of the <body> element of a theme’s *header.php* template file.[wp\_footer()](https://developer.wordpress.org/reference/functions/wp_footer/ "Function Reference/wp footer")Goes in *footer.php*, just before the closing </body> tag.[wp\_meta()](https://developer.wordpress.org/reference/functions/wp_meta/ "Function Reference/wp meta")Typically goes in the <li>Meta</li> section of a Theme’s menu or sidebar.[comment\_form()](https://developer.wordpress.org/reference/functions/comment_form/ "Function Reference/comment form")Goes in *comments.php* directly before the file’s closing tag (</div>).Take a look at a core theme’s templates for examples of how these hooks are used. --- # Required Theme Files Source: https://developer.wordpress.org/themes/releasing-your-theme/required-theme-files/ **Block theme:** See [Create a Block Theme](https://developer.wordpress.org/block-editor/how-to-guides/themes/create-block-theme/) for building a block theme Classic themes must include the required theme files. These files must follow template file standards set by the themes team. For Classic themes, additional standard template files are recommended to use. Learn more about the [Organizing Theme Files](https://developer.wordpress.org/themes/basics/organizing-theme-files/). ## Classic Themes Required Theme Files 1. **style.css** Your theme’s main [stylesheet](https://developer.wordpress.org/themes/basics/including-css-javascript/) file. This file will also include information about your theme, such as author name, version number, and plugin URL, in it’s header. 2. **index.php** The main [template](https://developer.wordpress.org/themes/basics/template-files/) file for your theme. This will be the template for the homepage on your site unless a static front page is specified. If you *only* include this template file, it must include all functionality of your theme. However, you can use as many relevant template files as you want in your theme. 3. ****comments.php**** The comment template which is included wherever comments are allowed. This file should provide support for threaded comments and trackbacks, and should style author comments differently then user comments. See the [Comments](https://developer.wordpress.org/themes/functionality/comments/) page for more information. 4. **screenshot** In the WordPress.org theme directory, the screenshot acts as a visual indicator of what your theme looks like. It is visible both in the web view and in the admin dashboard. The screenshot must not be bigger than 1200 x 900px. While these files are the only files required by the theme review team for acceptance into the WordPress.org theme directory, you may use other template files. Of course, any file mentioned in the tutorial in this handbook may be used in your theme. --- # Testing Source: https://developer.wordpress.org/themes/releasing-your-theme/testing/ If you’ve followed this handbook, you’ll already have a good grasp on the testing required before submitting your theme to the WordPress.org theme directory. If you haven’t, this page will give you a quick refresher. Testing is incredibly important before releasing a theme. You may have built the most beautiful WordPress theme, but if it breaks when someone tries to comment or insert an image, your theme isn’t ready for real world usage. Before testing your theme, make sure you’ve setup a development environment. There are a number of ways to setup your environment, many of which are documented on the [Setting up a Development Environment](https://developer.wordpress.org/themes/getting-started/setting-up-a-development-environment/) page. ## Theme Unit Test After you’ve setup your development environment, you’ll need test content to test your theme with. While you can create your own test content, the theme review team has created the [Theme Unit Test](https://codex.wordpress.org/Theme_Unit_Test), which includes many different types of content. This will help ensure that your theme works in circumstances you may not have anticipated. The Theme Unit Test is a WordPress export file that can be imported into any WordPress installation by using the WordPress Importer. You should import it into your local development environment. ## WordPress Settings Making tweaks and changes to your WordPress installation is another good way to ensure that you’ve built your theme to handle numerous scenarios. Use the following settings to test your theme. **General** Set the Site Title to something long and set the Tagline to something even longer. These settings will test how your theme handles edge cases for site titles and taglines. **Reading** Set “Blog pages show at most” to 5. This setting will ensure that index/archive pagination is triggered. **Discussion** Enable “Threaded Comments” at least 3 levels deep. This setting will facilitate testing of your theme’s comment list styling. Enable “Break comments into pages” and set 5 comments per page to test the pagination and styling of comments. **Media** Remove the values for the large size of media to test the theme’s `$content_width` setting. **Permalinks** Change the permalink setting a few times to ensure your theme can handle various URL formats. For more setup instructions, take a look at the [Theme Unit Test](https://codex.wordpress.org/Theme_Unit_Test#Setup) page in the WordPress Codex. ## WordPress Beta Tester WordPress releases happen three times a year. It’s a good idea to test your theme against the next version of WordPress so you can anticipate issues when the next version is released. This can be done easily with the [WordPress Beta Tester](https://wordpress.org/plugins/wordpress-beta-tester/) plugin. The plugin makes it easy to download either the latest nightly version of WordPress or the latest branch version (for minor bugfix releases). This is especially useful when anticipating a new major release or developing for an upcoming feature. ## Testing and debugging tools ### Theme Check Each theme goes through an automated check before a reviewer even sees it. If there are any immediate problems with the theme, identified by the automated check, the theme will be rejected with notes on how to resolve the issues. The [Theme Check](https://wordpress.org/plugins/theme-check/) plugin adds a dashboard link under Appearance so you can run the exact same checks that WordPress.org does right from your administration panel. Doing this prior to uploading your theme lets you know what needs to be addressed prior to submission. Running the check will give you a list of any warnings your theme has generated and what items are required for the theme to be accepted in the WordPress.org theme directory, as well as any recommended items that may be missing from your theme. ### Developer The [Developer](https://wordpress.org/plugins/developer/) plugin is really just a tool to automatically download and install some of the plugins you’ll want when developing your theme. Some of the ones discussed in this handbook will already be installed and active. Others you can install as soon as you activate the plugin. ### Debug Bar [Debug Bar](https://wordpress.org/plugins/debug-bar/) pushes all debug messages to a separate page where they are listed in an easy-to-read layout and organized by type of message. There are also a number of [other plugins](https://wordpress.org/plugins/search.php?q=debug+bar) that add on to Debug Bar, extending its features or adding more information. ### Log Deprecated Notices [Log Deprecated Notices](https://wordpress.org/plugins/log-deprecated-notices/) displays a list of the deprecated function notices in your theme and where the code can be found. This should be run, at minimum, after every major release of WordPress, so you can resolve and remove any deprecated code and functions from your theme. ### Browser testing When submitting your theme to WordPress.org, it’s expected that it works well in modern browsers and at any resolution. You should test your theme against a number of popular browsers before submitting, both mobile and desktop. Many browsers have built-in features making it easy to test, for example the [Chrome Developer Tools](https://developer.chrome.com/devtools), [Firefox Developer Tools](https://developer.mozilla.org/en-US/docs/Tools), and the [Microsoft Edge tools](http://dev.modern.ie). Note that [Internet Explorer is no longer supported by WordPress](https://make.wordpress.org/core/2021/04/22/ie-11-support-phase-out-plan/) since 5.8 release. ### Validation Likewise, your theme should use valid HTML5 and CSS code. There are a variety of tools that will test your site for valid code, include [this HTML5 validator](http://html5.validator.nu/) and [this CSS validator](http://jigsaw.w3.org/css-validator/). --- # Theme Review Guidelines Source: https://developer.wordpress.org/themes/releasing-your-theme/theme-review-guidelines/ The [WordPress Themes Team](https://make.wordpress.org/themes "https://make.wordpress.org/themes") provides and maintains the theme review guidelines as part of their task as WordPress Contributors and Developers for the [WordPress Theme Directory](https://wordpress.org/themes/). Some of these guidelines are required before themes are included in the theme directory. Other guidelines are recommendations for best practices in developing your theme and making it available to as many people as possible. This handbook uses both recommendations and requirements from the theme review guidelines to ensure the theme you develop is accessible to everyone. The requirements for being included in the WordPress.org theme directory can be found [here](https://make.wordpress.org/themes/handbook/review/required/). ## Get Involved The WordPress Themes Team is [open to anyone](https://make.wordpress.org/themes/handbook/get-involved/become-a-reviewer/) and is a great way to get a better understanding of how themes are developed. To become a member of the WordPress Themes Team, read through the [WordPress Themes Team’s site](https://make.wordpress.org/themes/). --- # Writing Documentation Source: https://developer.wordpress.org/themes/releasing-your-theme/writing-documentation/ Documentation is important for themes as it provides a way for users to understand what a theme does and does not support. Likewise, documenting the code of your theme will make it easier for other theme developers to customize your theme, likely with a [child theme](https://developer.wordpress.org/themes/advanced-topics/child-themes/). Here’s a list of **requirements** and **recommendations** for your theme’s documentation. - Themes are **required** to provide end-user documentation of any design limitations or extraordinary installation/setup instructions. - Themes are **required** to include a [readme.txt file](https://wordpress.org/plugins/about/readme.txt), using the plugin directory’s readme.txt markdown format. New themes need to follow this rule as of October 25th, 2018. Old themes have a 6 months grace time from this date. Since WordPress 5.8 theme [readme files are not parsed for requirements](https://core.trac.wordpress.org/ticket/48520). This means that headers `Requires PHP` and `Requires at least` are going to be parsed from theme’s `style.css` file. --- # Submitting Your Theme to WordPress.org Source: https://developer.wordpress.org/themes/releasing-your-theme/submitting-your-theme-to-wordpress-org/ Before themes are added to the WordPress Theme Directory, they are closely reviewed by the [Themes team](https://make.wordpress.org/themes/) to make sure they adhere to basic [guidelines](https://make.wordpress.org/themes/handbook/review/required/). This review ensures that WordPress users across the globe can download themes that are high quality and secure. ## Need Help? If you have theme development questions, please post them in the [Developing with WordPress](https://wordpress.org/support/forum/wp-advanced/) forum. Volunteers from around the world are ready to assist you with the development of your theme. ## Guidelines Make sure you review the [Theme Review Guidelines](https://make.wordpress.org/themes/handbook/review/required/) before uploading a theme. If you have questions about these guidelines, you can ask them in the [\#themes](https://wordpress.slack.com/messages/themes) channel in [Slack](https://chat.wordpress.org/). Anyone with a WordPress.org account can access the Making WordPress Slack. ## Testing With Sample Data The [WordPress Themes Team](https://make.wordpress.org/themes/) will be reviewing your theme using the sample data from the [Theme Unit Test](https://developer.wordpress.org/themes/release/testing/). Before uploading your theme for review, please test it with this sample export data. ## Uploading Your Theme When you are ready to submit your theme for review, please upload your theme ZIP at [Themes > Upload](https://wordpress.org/themes/getting-started/). Future updates are to be uploaded via the same page. More information about the theme review process is available on the [Themes Team website](https://make.wordpress.org/themes/handbook/review/). --- # Template Files Source: https://developer.wordpress.org/themes/basics/template-files/ Template files are used throughout WordPress themes, but first let’s learn about the terminology. ## Template Terminology The term “template” is used in different ways when working with WordPress themes: - Templates files exist within a theme and express how your site is displayed. - [Template Hierarchy](https://developer.wordpress.org/themes/basics/template-hierarchy/) is the logic WordPress uses to decide which theme template file(s) to use, depending on the content being requested. - [Page Templates](https://developer.wordpress.org/themes/template-files-section/page-template-files/ "Page Templates") are those that apply to pages, posts, and custom post types to change their look and feel. **In classic themes,** [Template Tags](https://developer.wordpress.org/themes/basics/template-tags/ "Template Tags") are built-in WordPress functions you can use inside a template file to retrieve and display data (such as [`the_title()`](https://developer.wordpress.org/reference/hooks/the_title/ "Function Reference/the title") and [`the_content()`](https://developer.wordpress.org/reference/hooks/the_content/ "Function Reference/the content")). **In block themes,** blocks are used instead of template tags. ## Template files WordPress themes are made up of template files. - In classic themes these are PHP files that contain a mixture of HTML, [Template Tags](https://developer.wordpress.org/themes/basics/template-tags/ "Template Tags"), and PHP code. - In block themes these are HTML files that contain HTML markup representing blocks. When you are building your theme, you will use template files to affect the layout and design of different parts of your website. For example, you would use a `header` template or template part to create a header. When someone visits a page on your website, WordPress loads a template based on the request. The type of content that is displayed by the template file is determined by the [Post Type](https://developer.wordpress.org/themes/basics/post-types/) associated with the template file. The [Template Hierarchy](https://developer.wordpress.org/themes/basics/template-hierarchy/ "Template Hierarchy") describes which template file WordPress will load based on the type of request and whether the template exists in the theme. The server then parses the code in the template and returns HTML to the visitor. The most critical template file is `the index`, which is the catch-all template if a more-specific template can not be found in the [template hierarchy](https://developer.wordpress.org/themes/basics/template-hierarchy/). Although a theme only needs a `index` template, typically themes include numerous templates to display different content types and contexts. ## Template partials A template part is a piece of a template that is included as a part of another template, such as a site header. Template part can be embedded in multiple templates, simplifying theme creation. Common template parts include: - `header.php` or `header.html` for generating the site’s header - `footer.php` or `footer.html` for generating the footer - `sidebar.php` or `sidebar.html` for generating the sidebar While the above template files are special-case in WordPress and apply to just one portion of a page, you can create any number of template partials and include them in other template files. In block themes, template parts must be placed inside a folder called parts. ## Common WordPress template files Below is a list of some basic theme templates and files recognized by WordPress. **index.php (classic theme) or index.html (block theme)** The main template file. It is **required** in all themes. **style.css** The main stylesheet. It is **required** in all themes and contains the information header for your theme. **rtl.css** The right-to-left stylesheet is included automatically if the website language’s text direction is right-to-left. **front-page.php (classic theme) or front-page.html (block theme)** The front page template is always used as the site front page if it exists, regardless of what settings on **Admin > Settings > Reading**. **home.php (classic theme) or home.html (block theme)** The home page template is the front page by default. If you do not set WordPress to use a static front page, this template is used to show latest posts. **singular.php (classic theme) or singular.html (block theme)** The singular template is used for posts when `single.php` is not found, or for pages when `page.php` are not found. If `singular.php` is not found, `index.php` is used. **single.php (classic theme) or single.html (block theme)** The single post template is used when a visitor requests a single post. **single-{post-type}.php (classic theme) or single-{post-type}.html (block theme)** The single post template used when a visitor requests a single post from a custom post type. For example, `single-book.php` would be used for displaying single posts from a custom post type named *book*. **archive-{post-type}.php (classic theme) or archive-{post-type}.html (block theme)** The archive post type template is used when visitors request a custom post type archive. For example, `archive-books.php` would be used for displaying an archive of posts from the custom post type named *books*. The archive template file is used if the `archive-{post-type} template` is not present. **page.php (classic theme) or page.html (block theme)** The page template is used when visitors request individual pages, which are a built-in template. **page-{slug}.php (classic theme) or page-{slug}.html (block theme)** The page slug template is used when visitors request a specific page, for example one with the “about” slug (page-about.php). **category.php (classic theme) or category.html (block theme)** The category template is used when visitors request posts by category. **tag.php (classic theme) or tag.html (block theme)** The tag template is used when visitors request posts by tag. **taxonomy.php (classic theme) or taxonomy.html (block theme)** The taxonomy term template is used when a visitor requests a term in a custom taxonomy. **author.php (classic theme) or author.html (block theme)** The author page template is used whenever a visitor loads an author page. **date.php (classic theme) or date.html (block theme)** The date/time template is used when posts are requested by date or time. For example, the pages generated with these slugs: http://example.com/blog/2014/ http://example.com/blog/2014/05/ http://example.com/blog/2014/05/26/ **archive.php (classic theme) or archive.html (block theme)** The archive template is used when visitors request posts by category, author, or date. **Note**: this template will be overridden if more specific templates are present like `category.php`, `author.php`, and `date.php`. **search.php (classic theme) or search.html (block theme)** The search results template is used to display a visitor’s search results. **attachment.php (classic theme) or attachment.html (block theme)** The attachment template is used when viewing a single attachment like an image, pdf, or other media file. **image.php (classic theme) or image.html (block theme)** The image attachment template is a more specific version of `attachment.php` and is used when viewing a single image attachment. If not present, WordPress will use `attachment.php` instead. **404.php (classic theme) or 404.html (block theme)** The 404 template is used when WordPress cannot find a post, page, or other content that matches the visitor’s request. **comments.php** The comments template in classic themes. In block themes, blocks are used instead. ## Using template files ### Classic themes In classic themes, within WordPress templates, you can use [Template Tags](https://developer.wordpress.org/themes/basics/template-tags/ "Template Tags") to display information dynamically, include other template files, or otherwise customize your site. For example, in your `index.php` you can include other files in your final generated page: - To include the header, use [get\_header()](https://developer.wordpress.org/reference/functions/get_header/ "Function Reference/get header") - To include the sidebar, use [get\_sidebar()](https://developer.wordpress.org/reference/functions/get_sidebar/ "Function Reference/get sidebar") - To include the footer, use [get\_footer()](https://developer.wordpress.org/reference/functions/get_footer/ "Function Reference/get footer") - To include the search form, use [get\_search\_form()](https://developer.wordpress.org/reference/functions/get_search_form/ "Function Reference/get search form") - To include custom theme files, use [get\_template\_part()](https://developer.wordpress.org/reference/functions/get_template_part/ "Function Reference/get template part") Here is an example of WordPress template tags to *include* specific templates into your page: ```php ``` There’s an entire page on [Template Tags](https://developer.wordpress.org/themes/basics/template-tags/ "Template Tags") that you can dive into to learn all about them. Refer to the section [Linking Theme Files & Directories](https://developer.wordpress.org/themes/basics/linking-theme-files-directories/ "Linking Theme Files & Directories") for more information on linking component templates. ### Block themes In block themes you use blocks instead of template tags. Block markup is the HTML code that WordPress uses to display the block. Template parts are blocks, and you add them to your template files the same way as you add blocks. To include a header or footer template part, add the block markup for the template part. The `slug` is the name of the part. If the file you want to include is called `header.html`, then the slug is “header”: ```markup (your page content) ``` To include the search form, use the block markup for the search block: ```markup ``` --- # Reworking Theme Files & Organization Source: https://developer.wordpress.org/themes/basics/reworking-theme-files-organization/ ![basics-theme-files-organization-01](https://i0.wp.com/developer.wordpress.org/files/2014/08/basics-theme-files-organization-01.jpg?resize=1024%2C384&ssl=1) ## Theme folder and file structure While WordPress themes technically only require two files (`index.php` and `style.css`), they usually are made up of many files and can become quickly disorganized. In the last section, [Template Files](# "Template Files"), you set up your `header.php, footer.php, page.php, home.php, and single.php` files. Let’s look at the [Twenty Twelve theme](https://wordpress.org/themes/twentytwelve) default themes as one example of good file structure and organization. While this may be a bit overwhelming at first, let’s break it down. Can you find the templates you just built? ![basics-theme-files-organization-02](https://i0.wp.com/developer.wordpress.org/files/2014/08/basics-theme-files-organization-02.png?resize=629%2C1500&ssl=1) While there are still a lot of files, their names help provide a context of what they are. Basically each file handles a feature of WordPress. I.e. `comments.php` deals with how the theme will handle comments; `image.php` instructs the theme how to handle images, etc. Don’t worry about adding these files unless you need them. You can see that the main theme template files are in the theme’s root directory, while JavaScript, languages, CSS, and page template files are placed within their own folders. At this time there are **no required folders within a WordPress theme**. However, WordPress does recognize the following folders by default: ### Page templates folder ![basics-theme-files-organization-03](https://i0.wp.com/developer.wordpress.org/files/2014/08/basics-theme-files-organization-03.png?resize=400%2C124&ssl=1) The [custom page templates](https://developer.wordpress.org/themes/basics/page-templates/ "Custom Page Templates"), named *page-templates* (since: 3.4.0) allows for better organization of template files. Custom page template files placed in this folder are automatically recognized by WordPress. ### Language folder ![basics-theme-files-organization-04](https://i0.wp.com/developer.wordpress.org/files/2014/08/basics-theme-files-organization-04.png?resize=400%2C85&ssl=1) If you wish to [internationalize your theme](https://developer.wordpress.org/themes/functionality/internationalization/ "Internationalization") so it’s usable in other languages, you can create a *languages* folder to contain translations. --- # Updating Your Theme Source: https://developer.wordpress.org/themes/releasing-your-theme/updating-your-theme/ There are two ways to update your theme, by uploading a Zip file or using subversion (SVN). ## Uploading a Zip file While your theme is in the queue and waiting for review, you can update your theme by [uploading a Zip file](https://wordpress.org/themes/getting-started/). Just as you initially uploaded. Be sure to update the version number on style.css before uploading. Updating the version number will NOT change the queue position of your theme while waiting for the review. If you already have your themes in the repository, you can either update by uploading a Zip file or via SVN. ## Subversion GUI clients Several GUI clients are available for Windows users. [TortoiseSVN](https://tortoisesvn.net/) is one of the popular Free clients. [SmartSVN](https://www.smartsvn.com/) is a paid application that works on Windows, Linux, and macOS. For Mac users, SVN helps streamline the automation process, including removing `.DS_Store` and `__MACOSX` hidden files and folders that often trigger the theme check errors. ### Important notes: **(1) Directory naming guidelines** The theme author must create a new directory before uploading the theme. It is important to name the new directory with the new version number. For example, if the current theme is version `1.0.1`, the name for the new directory must be *`1.0.2`*. **(2) Version numbering** Version numbering must follow a standard version naming convention. New version must be higher than the current version. For example, if your current theme is `1.2.3`, the new version must be `1.2.4`. **(3) SVN is not a development tool** Unlike Github, SVN is not a development tool. You should upload your theme only when you are ready to release a new version. Once you commit, the changes cannot be overwritten. If you find a mistake, even a small typo, there is no way to make changes. The only way to make corrections is to create another directory with a newer version number and upload it again. ### Uploading your themes using SVN on MacOS **What you will need** - MacOS - VS code - SVN extension for VS code To check whether you have svn installed, type `svn --version` in the terminal. (1) Create a copy of the repository on your local machine. Replace */NameOfYourTheme/* with your theme name. `svn co https://themes.svn.wordpress.org/NameOfYourTheme/` For example, if your theme name is Hello World, use `svn co https://themes.svn.wordpress.org/hello-world/` **Tips:** If you are not sure about the exact name of your theme (e.g. hyphen, underscore), you can find it at [this link](https://themes.svn.wordpress.org/). (2) The next step is to create a new directory and copy all theme files, including the history from the current version of the theme. In the example below, we are creating a new directory 1.0.2, and copying all files from the version 1.0.1. `svn cp 1.0.1 1.0.2` (3) Make changes to your theme. **Note:** Make sure to update the version number on style.css, and the changelog on readme.txt (4) Remove *.DS\_Store* hidden file. `find . -name ".DS_Store" -print -delete` (5) Next, remove `__MACOSX` folder. `rm -R __MACOSX` (6) Finally, you are ready to commit. `svn commit -m “Fix typo on readme.txt”` **Note:** Once you commit, there is no way to change or modify what you just committed. If you find a mistake, Repeat the process from step 2. ### What to expect next Once you successfully upload the new update, you will receive a confirmation email from WordPress.org. It may take some time to reflect on the WordPress.org directory. --- # Classic themes Source: https://developer.wordpress.org/themes/classic-themes/ In this section you will find information about developing classic WordPress themes. --- # Block theme accessibility Source: https://developer.wordpress.org/themes/functionality/block-theme-accessibility/ Block themes support accessibility and simplify the process for adding accessibility. ## Landmark Group, Template part, and Query blocks can become a landmark. There are two ways to create landmark. **Using block markup** `”tagName":"header”` creates header landmark. ```

    ``` **Using site editor** HTML element under Advanced section in the Block panel provides the following landmark options. HTML element under Advanced section in the Block panel provides the following landmark options. `
    ` `
    ` `
    ` `
    ` `
    ` `
    `. ## Skip to content By selecting `
    ` landmark on Group, Template part, or Query block generates the Skip to Content link. Learn more about the [skip to content link here](https://make.wordpress.org/themes/handbook/review/required/#3-accessibility). ```

    Hello World

    Welcome to WordPress. This is your first post.

    ``` ## Accessible navigation menu Navigation block enables the following accessibility without additional code. - Support responsive view - Support keyboard navigation - Insert `
    ` landmark role - Insert ARIA attributes `aria-label` `aria-hidden` ## Additional resources - [Accessibility](https://make.wordpress.org/themes/handbook/review/accessibility/) Changelog: - **Updated** 2023-03-08 Updated code examples to reflect WordPress 6.1 block markup. - **Created** 2022-01-25 --- # Tools & Resources Source: https://developer.wordpress.org/themes/basics/tools-resources/ Whether you’re building your very first theme or your tenth, the following resources are meant to help ease the process. Keep in mind that there are various community tools not mentioned here as well but that still might aid in your efforts. ## Block themes A block theme is a type of WordPress theme built using blocks. You can read more about these themes in the [Block Theme section](https://developer.wordpress.org/themes/block-themes/). [**Create Block Theme plugin**](https://wordpress.org/plugins/create-block-theme/) This plugin was created by various community members. This tool can create standalone block themes and child themes, depending on your needs. Here are the high-level steps: 1. Install and activate the [Create Block Theme](https://github.com/WordPress/create-block-theme) plugin. You will also need to be running the latest version of the [Gutenberg](https://wordpress.org/plugins/gutenberg/) plugin. 2. Make changes to your site design using the Customizer and Site Editor. 3. Edit your templates using the Site Editor. For some things, you might need to edit the template files again later. 4. In the WordPress Admin Dashboard, under Appearance there will be a new page called “Create Block Theme”. You can add the details for the theme here. These details will be used in the style.css file. 5. Click the “Create Block Theme” button. From there, a zip file will be downloaded which will contain all the files for your theme. [**Theme Generator**](https://fullsiteediting.com/block-theme-generator/) This tool was created by Carolina Nymark and it allows you to create three different types of themes to start from: - No Code: for non-developers who want to start from a blank theme and build directly in the Site Editor. - Empty: for developers to make their own with six templates and a theme.json with empty settings for you to complete. - Basic: for developers to explore with six templates, two template parts, three block patterns, and two custom block styles alongside some initial theme.json settings. - Advanced: for developers to explore with seven templates, five template parts, seven patterns, various block styles, and a more robust theme.json. It’s common to want to remove some of the examples. **Comparison Chart** | **Tool** | **Child theme options?** | **Template creation?** | **Theme.json Controls** | **Demo content** | |---|---|---|---|---| | Create Block Theme plugin | Yes | Yes | No | No | | Theme Generator | No | Yes | Yes | Yes | ## Classic themes A classic theme is built with PHP templates, functions.php, and more. You can read more about these themes in the [Classic Theme section](https://developer.wordpress.org/themes/classic-themes/). The [\_s (Underscores)](https://underscores.me/) starter theme is a tool for initializing and creating a classic theme. ## Tools **WordPress Coding Standards for PHP\_CodeSniffer** This project is a collection of [PHP\_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer) rules (sniffs) that are used to validate code developed for WordPress, but can also be used when developing themes and plugins. They encompass coding style along with established best practices regarding interoperability, translatability, and security in the WordPress ecosystem, according to the official [WordPress Coding Standards](https://make.wordpress.org/core/handbook/best-practices/coding-standards/). [WordPress Coding Standards for PHP\_CodeSniffer](https://github.com/WordPress/WordPress-Coding-Standards) The WPThemeReview Standards for PHP\_CodeSniffer are a collection of sniffs that aim to automate the code analysis part of the [Theme Review Process](https://make.wordpress.org/themes/handbook/review/) as much as possible using static code analysis. The WPThemeReview Standards require the WordPress Coding Standards. [WPThemeReview Standards for PHP\_CodeSniffer](https://github.com/WPTT/WPThemeReview) [**Theme Check Plugin**](https://wordpress.org/plugins/theme-check/) The theme check plugin is an easy way to test your theme and make sure it’s up to spec with the latest [theme review](https://make.wordpress.org/themes/handbook/review/) standards. With it, you can run all the same automated testing tools on your theme that WordPress.org uses for theme submissions. This allows you to resolve any issues that might come up before trying to submit your theme to the theme repository. ## Training material Site Design with Full Site Editing: [Part 1](https://learn.wordpress.org/course/simple-site-design-with-full-site-editing/), [Part 2](https://learn.wordpress.org/course/part-2-personalized-site-design-with-full-site-editing-and-theme-blocks/), [Part 3](https://learn.wordpress.org/course/part-3-advanced-site-design-with-full-site-editing-site-editor-templates-and-template-parts/) [Anatomy of a Block Theme](https://learn.wordpress.org/tutorial/anatomy-of-a-block-theme/) [Creating a landing page with a block theme](https://learn.wordpress.org/tutorial/creating-a-landing-page-with-a-block-theme/) [Building a home page with a block theme](https://learn.wordpress.org/tutorial/building-a-home-page-with-a-block-theme/) [Using Schema with WordPress theme.json](https://learn.wordpress.org/tutorial/using-schema-with-wordpress-theme-json/) [Create a Basic Child Theme for Block Themes](https://learn.wordpress.org/lesson-plan/create-a-basic-child-theme-for-block-themes/) Find more theme lessons on [learn.wordpress.org](https://learn.wordpress.org/?s=theme). --- # Theme security issues Source: https://developer.wordpress.org/themes/theme-security/theme-security-issues/ Please do not report security issues with WordPress Core to the themes team. To report an issue with WordPress itself, [follow the directions for reporting security vulnerabilities.](https://make.wordpress.org/core/handbook/testing/reporting-security-vulnerabilities/) If you have found a **plugin** with a security issue, please read [Reporting Plugin Security Issues](https://developer.wordpress.org/plugins/wordpress-org/plugin-security/reporting-plugin-security-issues/) ## How to report a theme If you find a theme with a security issue, please **do not** post about it publicly anywhere. Even if there’s a report filed on one of the official security tracking sites, bringing more awareness to the security issue tends to increase people being hacked, and rarely speeds up the fixing. To report a theme that is in the WordPress.org theme directory, please go to the theme’s directory listing (For example, ) and use the “**Report this theme**” button in the sidebar, and complete the form. [![](https://i0.wp.com/make.wordpress.org/themes/files/2023/09/report_theme.jpg?ssl=1)](https://i0.wp.com/make.wordpress.org/themes/files/2023/09/report_theme.jpg?ssl=1) You can also send reports of security issues to `themes@wordpress.org`. Include the following: - a clear and concise description of the issue - a link to the specific theme - whether or not you have validated the security issue yourself - **optional** – links to any public disclosures on 3rd party sites ## For developers ### What to do when you receive a request to update your theme If your theme has been reported and the Themes Team decides that action needs to be taken, you will receive an email from the Themes Team with information and instructions. – You may be asked to solve an issue within a specific time frame. This depends on the severity of the issue. – The Themes Team may need to suspend your theme to prevent new downloads until the issue is resolved. **You must reply to the email if you have any questions, need more information, or need more time.** Test your theme update carefully and submit it through the [upload form on the theme directory page](https://wordpress.org/themes/upload/). [Learn more about how the Themes team works with theme suspensions and delisting](https://make.wordpress.org/themes/handbook/review/theme-suspension/). ### Resources To learn more about theme security, please see the [Security chapter of the common APIs handbook](https://developer.wordpress.org/apis/security/). https://developer.wordpress.org/themes/theme-security/common-vulnerabilities > [A Guide to Writing Secure Themes – Part 1: Introduction](https://make.wordpress.org/themes/2015/05/19/a-guide-to-writing-secure-themes-part-1-introduction/) > [A Guide to Writing Secure Themes – Part 2: Validation](https://make.wordpress.org/themes/2015/05/26/a-guide-to-writing-secure-themes-part-2-validation/) > [A Guide to Writing Secure Themes – Part 3: Sanitization](https://make.wordpress.org/themes/2015/06/02/a-guide-to-writing-secure-themes-part-3-sanitization/) > [A Guide to Writing Secure Themes – Part 4: Securing Post Meta](https://make.wordpress.org/themes/2015/06/09/a-guide-to-writing-secure-themes-part-4-securing-post-meta/) --- # Global Settings and Styles (theme.json) Source: https://developer.wordpress.org/themes/global-settings-and-styles/ Welcome to the Global Settings and Styles documentation. In this chapter you will learn everything you need to know about configuring settings, styles, and more via your theme’s `theme.json` file. `theme.json` is a foundational piece of block theming. While it is not a strictly required file, you will need to work with it for nearly any theme project. It is useful for everything from configuring colors to defining default typography settings to applying front-end styles to your theme. ## Navigating this chapter Use the below links to find the topic you are looking for in this chapter. Each section of the chapter is set up to offer a straightforward learning path toward learning the ins-and-outs of `theme.json` for first-time themers. But if you are already familiar with the foundational concepts, feel free to skip ahead to the topic you want to learn more about. - [**Introduction to `theme.json`**](https://developer.wordpress.org/themes/global-settings-and-styles/introduction-to-theme-json/)**:** A walkthrough of setting up your `theme.json` file, introducing you to the foundational concepts for configuring global settings and styles for your theme. - [**Settings**](https://developer.wordpress.org/themes/global-settings-and-styles/settings/)**:** Documentation for each of the standard and custom settings that you can configure via `theme.json`. Sub-pages document every available setting. - [**Styles**](https://developer.wordpress.org/themes/global-settings-and-styles/styles/)**:** Learn how to use the standard design system to apply styles through `theme.json`, which also integrate with the user interface. - [**Custom Templates**](https://developer.wordpress.org/themes/global-settings-and-styles/custom-templates/)**:** How to register custom post, page, and CPT (custom post type) templates for your theme. - [**Template Parts**](https://developer.wordpress.org/themes/global-settings-and-styles/template-parts/)**:** How to register custom template parts that can be reused across your theme. - [**Patterns**](https://developer.wordpress.org/themes/global-settings-and-styles/patterns/)**:** How to bundle patterns from the official patterns repository with your theme. - [**Style Variations**](https://developer.wordpress.org/themes/global-settings-and-styles/style-variations/)**:** Documentation on creating custom `theme.json` style variations, giving your users alternative designs to choose from. --- # Introduction to theme.json Source: https://developer.wordpress.org/themes/global-settings-and-styles/introduction-to-theme-json/ `theme.json` is a configuration file that lets you define the global settings, styles, and more for your theme. The file works with both block and classic themes. When building a block theme, `theme.json` may be the most important file in the entire theme. In a way, it is the foundational piece that trickles down to every other component. That’s why this chapter is one of the most extensive in the handbook. Some of the things you can do with `theme.json` include (but are not limited to): - Enabling block features in the user interface, such as color, typography, and spacing controls. - Configuring a custom color palette, duotone filters, and background gradients. - Defining typographical features like font families, bundling web fonts, and more. - Adding your own CSS custom properties. - Adjusting the overall design by working within the core styles system. The settings and styles that you configure in `theme.json` are ultimately reflected on both the front end of the site and WordPress’ built-in editors. As shown in this screenshot, you can see that a variation of the default Twenty Twenty-Three theme as it’s looks in the **Appearance > Editor** screen in the admin: [![WordPress Site Editor with the Styles panel open in the right sidebar.](https://i0.wp.com/developer.wordpress.org/files/2023/09/intro-styles-interface.jpg?resize=2048%2C1071&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/09/intro-styles-interface.jpg?ssl=1)Each part of that design is handled directly in `theme.json`, and the user can further customize it through the built-in **Styles** interface. `theme.json` represents what you might call a “common language” that allows WordPress, your theme, plugins, and users to effectively communicate. Because it is built atop a standardized system, each component plays a role in bringing the overall site to life. ## theme.json structure The `theme.json` file can be broken down into several top-level sections as shown in this code snippet: ```json { "$schema": "https://schemas.wp.org/trunk/theme.json", "version": 2, "settings": {}, "styles": {}, "customTemplates": {}, "templateParts": {}, "patterns": [] } ``` Throughout this chapter, you will learn about each of these properties and how you can work with them to turn the design in your imagination into a working theme. Customizing the `theme.json` file directly in your theme requires that you have some familiarity with JSON code. You don’t need to be an expert (*copying and pasting can get you pretty far*), but having some foundational knowledge of how to format JSON will definitely help. You should also have a baseline understanding of CSS. While you do not need to directly write CSS code in `theme.json`, many of the features are mapped to CSS properties and values. Understanding the relationship between `theme.json` settings and styles and their CSS counterparts will help you in the long run. For more information on JSON and CSS, read: - [MDN Web Docs: CSS](https://developer.mozilla.org/en-US/docs/Web/CSS) - [MDN Web Docs: JSON](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/JSON) ## theme.json properties As you could see in the previous section, the `theme.json` file has several top-level properties. Some of these accept just a single value, but most have nested sub-properties with their own values. These are the current top-level properties that you can set in `theme.json`: - **`version`:** The `theme.json` schema version you are building for. - **`$schema`:** Used for defining the supported JSON schema, which will integrate with many code editors to give you on-the-fly hints and error reporting. - **`settings`:** Used to define which block controls appear, configure presets, and more. - **`styles`:** Used to apply colors, font sizes, custom CSS, and other styles to the website and blocks. - **`customTemplates`:** Metadata for custom templates defined in your theme’s `/templates` folder. - **`templateParts`:** Metadata for template parts defined in your theme’s `/parts` folder. - **`patterns`:** An array of pattern slugs to be registered from the [Pattern Directory](https://wordpress.org/patterns/). ### Adding a version At the very least, you should set the `version` property in your `theme.json` file. This should be an integer that matches the API version used to read and understand your `theme.json` code. The API is currently at version `2`. You can always find the most up-to-date version via the [`theme.json` Living Reference](https://developer.wordpress.org/block-editor/reference-guides/theme-json-reference/theme-json-living/) document. The bear minimum code that your `theme.json` file should have is: ```json { "version": 2 } ``` All `theme.json` code examples in this handbook include the `version` property because it should always be set. Technically, you can leave the version out, but WordPress will read your code as if it was on version `1` of the API. Using an outdated version may mean that your code will not be valid, at least as it is documented here in the handbook. You should always strive to keep up to date with the latest API version and make sure it is set in your `theme.json` file. ### Adding a JSON schema An optional property that you can add to your `theme.json` is a URL to the JSON schema. This can be particularly helpful when working with any modern code editor. Adding the `$schema` property will give you on-the-fly hints and error reporting in many code editors and is highly recommended. To add support for JSON schema, add this to your `theme.json` file: ```json { "$schema": "https://schemas.wp.org/trunk/theme.json", "version": 2 } ``` Again, this is *technically* an optional property. But there is rarely a good reason to leave it out. It’s just good development practice to include it. ### Adding settings, styles, and more The other properties available to you via `theme.json` require more in-depth documentation than what can be covered in this introduction. They each have their own pages (and some with multiple sub-pages) in this chapter of the handbook. Now it’s time to really dive into learning more about `theme.json`. You can take these next documentation steps as you prefer, but these are listed in their recommended reading order: - [**Settings**](https://developer.wordpress.org/themes/global-settings-and-styles/settings/)**:** Documentation for each of the standard and custom settings that you can configure via `theme.json`. - [**Styles**](https://developer.wordpress.org/themes/global-settings-and-styles/styles/)**:** Learn how to use the standard design system to apply styles through `theme.json`, which also integrate with the user interface. - [**Custom Templates**](https://developer.wordpress.org/themes/global-settings-and-styles/custom-templates/)**:** How to register custom post, page, and CPT (custom post type) templates for your theme. - [**Template Parts**](https://developer.wordpress.org/themes/global-settings-and-styles/template-parts/)**:** How to register custom template parts that can be reused across your theme. - [**Patterns**](https://developer.wordpress.org/themes/global-settings-and-styles/patterns/)**:** How to bundle patterns from the official patterns repository with your theme. - [**Style Variations**](https://developer.wordpress.org/themes/global-settings-and-styles/style-variations/)**:** Documentation on creating custom `theme.json` style variations, giving your users alternative designs to choose from. --- # Settings Source: https://developer.wordpress.org/themes/global-settings-and-styles/settings/ The `settings` property in `theme.json` lets you configure a wide range of settings for a WordPress install. It covers everything from color presets, to enabling typography design tools, to layout, and a little bit of everything in between. This document contains links for learning about each of these settings, which have their own individual documentation pages. ## The settings property `settings` is a top-level property in `theme.json` and has multiple nested properties that you can define. And some of those nested properties have multiple levels of nesting of their own. The following is an overarching look at these properties in the context of a `theme.json` file: ```json { "version": 2, "settings": { "appearanceTools": false, "border": {}, "color": {}, "custom": {}, "dimensions": {}, "layout": {}, "position": {}, "shadow": {}, "spacing": {}, "typography": {}, "useRootPaddingAwareAlignments": false, "blocks": {} } } ``` ## Settings documentation Use the following links to explore specific settings that you can configure in your `theme.json` file: - **[`appearanceTools`](https://developer.wordpress.org/themes/global-settings-and-styles/settings/appearance-tools/):** A catchall setting for enabling multiple other settings. - **`border`:** Used for controlling the border width, style, color, and radius. - **[`color`](https://developer.wordpress.org/themes/global-settings-and-styles/settings/color/):** Lets you register a color palette, gradients, duotone and configure color-related settings. - [`custom`](https://developer.wordpress.org/themes/global-settings-and-styles/settings/custom/): An object for adding custom settings, which are output as CSS custom properties. - **[`dimensions`](https://developer.wordpress.org/themes/global-settings-and-styles/settings/dimensions/):** Lets you configure the minimum height setting. - **[`layout`](https://developer.wordpress.org/themes/global-settings-and-styles/settings/layout/):** Used for setting layout properties like the content and wide widths. - **[`lightbox`](https://developer.wordpress.org/themes/global-settings-and-styles/settings/lightbox/):** Lets you configure the image lightbox feature. - **[`position`](https://developer.wordpress.org/themes/global-settings-and-styles/settings/position/):** Currently lets you define support for sticky positioning. - **[`shadow`](https://developer.wordpress.org/themes/global-settings-and-styles/settings/shadow/):** Lets you configure box-shadow support and define custom shadow presets. - **[`spacing`](https://developer.wordpress.org/themes/global-settings-and-styles/settings/spacing/):** Used for configuring spacing-related settings, such as margin and padding, - **[`typography`](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/):** Used for configuring typography-related settings, defining custom font sizes, and registering font families. - **[`useRootPaddingAwareAlignments`](https://developer.wordpress.org/themes/global-settings-and-styles/settings/use-root-padding-aware-alignments/):** A boolean setting for how padding on the root element should work. - **[`blocks`](https://developer.wordpress.org/themes/global-settings-and-styles/settings/blocks/):** An object for configuring per-block settings. The Theme Handbook also maintains a [reference for available settings](https://developer.wordpress.org/themes/global-settings-and-styles/settings/settings-reference/) based on the `theme.json` schema. --- # Styles Source: https://developer.wordpress.org/themes/global-settings-and-styles/styles/ The `styles` property in `theme.json` lets you configure settings at the global level, for individual elements, and individual blocks. WordPress supports a standard subset of the CSS specification, but also allows you to add custom CSS directly in your `theme.json` file. When possible, it is recommended to add your theme styles via the `styles` property, at least for standard WordPress features. This makes it possible for users to customize them via **Appearance > Editor > Styles** without CSS specificity issues. This document contains links for learning about the available style properties and how to apply styles to your theme via its `theme.json` file. ## The styles property `styles` is a top-level property in `theme.json` and has multiple nested properties that you can define. And some of those nested properties have multiple levels of nesting of their own. The following is an overarching look at these properties in the context of a `theme.json` file: ```json { "version": 2, "styles": { "elements": {}, "blocks": {} } } ``` The following is an example of what the `styles` property could look like in a custom `theme.json` file. This should give you a feel for how it is structured, but you will dive into this more deeply as you read through this section of the handbook: ```json { "version": 2, "styles": { "color": { "text": "#000000", "background": "#ffffff" }, "elements": { "button": { "color": { "text": "#ffffff", "background": "#000000" } } }, "blocks": { "core/code": { "color": { "text": "#ffffff", "background": "#000000" } } } } } ``` ## Styles documentation Use the following links to explore configuring styles via `theme.json` file: - **[Applying Styles](https://developer.wordpress.org/themes/global-settings-and-styles/styles/applying-styles/):** How to apply custom styles to your theme using the standard JSON syntax. - **[Using Presets](https://developer.wordpress.org/themes/global-settings-and-styles/styles/using-presets/):** How to use the presets that you’ve configured via the `settings` property in your styles. - **[Styles Reference](https://developer.wordpress.org/themes/global-settings-and-styles/styles/styles-reference/):** A reference guide for the available style properties that you can use in `theme.json`. --- # Custom Templates Source: https://developer.wordpress.org/themes/global-settings-and-styles/custom-templates/ WordPress lets you register custom templates in `theme.json`. More specifically, you can register single post, page, or CPT (custom post type) templates via the `customTemplates` property. It’s important to make the distinction that these templates are meant for single post/page/CPT templates and not for other types of templates. When registering these templates, your theme users can select them from the edit post screen, and their post’s design will match the template on the front end of the site. Custom templates give you a lot of flexibility in designing variations on your default post or page templates. For example, you could create a blank post template that only shows the content, design a page template with a sidebar, or even one that has no sidebars at all. Really, it depends on what your goals are for your theme project. This documentation is to teach you how to register custom templates via `theme.json`. For a more extensive look into how to build custom templates, check out the [Templates documentation](https://developer.wordpress.org/themes/templates/). ## Adding custom templates You can register custom templates via the `customTemplates` property in `theme.json`. It accepts an array of template objects, each defining an individual template. Each object passed to the `customTemplates` array supports these properties: - **`name`:** The name of your template file without the file extension. - **`title`:** A human-readable title for your template, which may be translated. - **`postTypes`:** An array of post type slugs that the template is usable on. This is an optional setting and defaults to the `page` post type. For block themes, WordPress will look for custom templates (all templates, actually) in the theme’s `/templates` folder. Therefore, if you register a template with the name of `example`, you must also have an `/templates/example.html` file in your theme. You can add as many custom templates as you want to your theme. Just keep in mind the usability aspect of offering too many choices. ### Registering a template Suppose you wanted to create a template named Content Canvas for both pages and posts. This template will only show the site header, post/page content, and site footer. Your users can select it when they need the full content area to behave as a sort of blank canvas. The first step you’d take is to create a `/templates/content-canvas.html` file in your theme. Don’t worry about adding anything to it yet; just leave it empty for the moment. Now register this template in `theme.json`, as shown below: ```json { "version": 2, "customTemplates": [ { "name": "content-canvas", "title": "Content Canvas", "postTypes": [ "page", "post" ] } ] } ``` If you edit a post or page in the WordPress admin, you should see the new **Content Canvas** option under the **Template** selector in the **Post/Page** sidebar panel: [![WordPress post editor with the Template select control highlighted in the right sidebar.](https://i0.wp.com/developer.wordpress.org/files/2023/09/custom-templates-canvas-select.jpg?resize=2048%2C1071&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/09/custom-templates-canvas-select.jpg?ssl=1)### Building a template Now let’s take care of actually building the template, at least for the sake of demonstration. Remember, you can learn more about building templates in the [Templates chapter](https://developer.wordpress.org/themes/templates/) of the handbook. Add this code to your `/templates/content-canvas.html` file: ```markup
    ``` This will give you a working template with an open content area. To see what this looks like in the site editor, head over to **Appearance > Editor** in the WordPress admin. Then, select **Content Canvas** under the **Templates** section: [![WordPress Site Editor showing the Content Canvas template on the screen.](https://i0.wp.com/developer.wordpress.org/files/2023/09/custom-templates-canvas-site-editor.jpg?resize=2048%2C1071&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/09/custom-templates-canvas-site-editor.jpg?ssl=1)This is just a demonstration of what is possible. The real power of custom templates is in what you build with them. --- # Patterns Source: https://developer.wordpress.org/themes/global-settings-and-styles/patterns/ The `patterns` property in `theme.json` lets you bundle patterns from the WordPress [Pattern Directory](https://wordpress.org/patterns/) with your theme. This is a neat system that lets you provide a wide variety of patterns that you’ve personally selected without having to design and build them yourself. Any pattern in the directory is available to you. [![Screenshot of the WordPress.org Pattern Directory, which displays a grid of block pattern demos.](https://i0.wp.com/developer.wordpress.org/files/2023/09/patterns-directory.jpg?resize=2048%2C1458&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/09/patterns-directory.jpg?ssl=1)And if you’re feeling adventurous, you can even submit your custom-designed patterns to the directory. This will let you both bundle them with your theme and let other theme creators and users use your patterns, even when your theme is not installed. In this document, you will learn how to include directory patterns for your theme’s users with just a few lines of code in `theme.json`. ## Adding patterns from the directory `patterns` is an optional property that lets you bundle as many or as few patterns as you’d like with your theme. The property accepts an array of pattern slugs, and as long as those patterns exist in the Patterns Directory, they will appear in the **Patterns** inserter in the WordPress editors. Here is a look at the `patterns` property in the default `theme.json`: ```json { "version": 2, "patterns": [] } ``` Let’s take a look at one of the patterns from the Pattern Directory: [Hero banner with overlap images](https://wordpress.org/patterns/pattern/hero-banner-with-overlap-images/). To find the slug for the pattern, you need to look in the address bar of your browser, which should give you this URL: ```markup https://wordpress.org/patterns/pattern/hero-banner-with-overlap-images/ ``` The slug is the part of the URL that comes after `https://wordpress.org/patterns/pattern/`. In this case, the slug is `hero-banner-with-overlap-images` (note that the final slash is not included). To include this pattern with your theme, you need to pass only the slug to the `patterns` array in `theme.json`: ```json { "version": 2, "patterns": [ "hero-banner-with-overlap-images" ] } ``` Now that you’ve got the basics down, pick out a couple of other patterns and add them to your `patterns` array in `theme.json`: ```json { "version": 2, "patterns": [ "fullscreen-cover-image-gallery", "hero-banner-with-overlap-images", "mixed-shape-gallery" ] } ``` Now you should see your chosen patterns in the **Patterns** inserter in the UI: [![Patterns inserter from the page-editing screen showing a list of Gallery-based patterns.](https://i0.wp.com/developer.wordpress.org/files/2023/09/patterns-dotorg.jpg?resize=2048%2C1071&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/09/patterns-dotorg.jpg?ssl=1)The patterns you include will automatically appear under the categories they are assigned to in the Pattern Directory. These are mapped to the existing patterns registered within WordPress. The patterns from the above example code all have the `gallery` pattern category, so they appear under the **Patterns > Gallery** tab in the inserter. --- # Template Parts Source: https://developer.wordpress.org/themes/global-settings-and-styles/template-parts/ Template parts are small sections (i.e., *parts*) that you can include in top-level templates. Following the DRY (Don’t Repeat Yourself) principle, they are generally used as sections that need to be reused across multiple templates. Instead of writing the code multiple times, you can break it apart into a single file and include it when needed. Because this chapter is focused on `theme.json`, the goal of this document is to explain how to register template parts within the `theme.json` file. You can dive more deeply into templates and template parts within the [Templates chapter](https://developer.wordpress.org/themes/templates/). In `theme.json`, you can register additional metadata for template parts, such as the title and area the part is assigned to. ## Registering template parts Technically, you can use custom template parts without ever registering them via `theme.json`. But registering them has some distinct advantages: - You can give the part a translatable title that is more appealing in the user interface. - You can assign each part to an area, creating a nicer user experience in the Site Editor. - It plays more nicely with plugins, style variations, and child themes that may grab, filter, or otherwise use the registered metadata in some way. To register template parts, you must pass an array of objects to the `templateParts` property in `theme.json`. Each object in the array accepts three key/value pairs: - **`area`:** The area that the template part belongs to. The default options are `header`, `footer`, and `uncategorized`. You can also assign it to any custom area. - **`name`:** The filename of your template part without the extension. - **`title`:** A human-readable title for your template, which may be translated. WordPress will look for template parts in the theme’s `/parts` folder. Therefore, if you register a template part with the name of `example`, you must also have a `/parts/example.html` file in your theme. You will learn more about template part areas in the Templates chapter. Also, check out the [Upgrading the site-editing experience with custom template part areas](https://developer.wordpress.org/news/2023/06/upgrading-the-site-editing-experience-with-custom-template-part-areas/) tutorial on the WordPress Developer Blog for an in-depth walkthrough of creating custom areas. ### Registering a template part The two most common template parts that any theme will register are for a site header and footer. This is also why WordPress has the default areas of `header` and `footer`. You are not required to use these parts or areas, but they are pretty much standard sections for nearly all websites. For this exercise, let’s register them both. First, add a couple of empty files named `header.html` and `footer.html` in your theme’s `/parts` folder if they do not already exist. You’ll add some block code to them in the next step. Now register those template parts in `theme.json`: ```json { "version": 2, "templateParts": [ { "area": "header", "name": "header", "title": "Header" }, { "area": "footer", "name": "footer", "title": "Footer" } ] } ``` It can be confusing when both the `area` and `name` values match. That’s not always the case, but is often how things look when dealing with the header and footer. Some theme authors prefer to name the `header` and `footer` template parts `site-header` and `site-footer` to better differentiate them. Feel free to do that if it makes more sense to you. Or rename them to anything you want. You are not limited to these two common template parts. You can add as many parts as you need for your theme project. ### Building a template part All template parts should be placed in your theme’s `/parts` folder (WordPress also recognizes the `/template-parts` folder for backwards compatibility). So you will now be editing the `/parts/header.html` and `/parts/footer.html` files. You will learn more about building custom template parts in the [Templates chapter](https://developer.wordpress.org/themes/templates/). For the purposes of this documentation, just consider the following code snippets as examples that you can customize. In your `/parts/header.html` file, add this code: ```markup
    ``` Then add this code to your `/parts/footer.html` file: ```markup

    Powered by WordPress.

    ``` Now go to **Appearance > Editor** in your WordPress admin and look at the **Patterns > Template Parts** section. You should see both the **Header** and **Footer** areas listed with your custom template parts: [![Templates screen in the WordPress Site Editor. The Header area is specifically selected, showing a single Header template part.](https://i0.wp.com/developer.wordpress.org/files/2023/09/template-parts-site-editor.jpg?resize=2048%2C1071&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/09/template-parts-site-editor.jpg?ssl=1)### Including a template part Creating template part files and registering them in `theme.json` does not mean that your parts will automatically appear on the site. Because they are only *parts*, you must also include them inside of a template. Remember, you’ll learn more about creating templates in the [Templates documentation](https://developer.wordpress.org/themes/templates/) if you are not already familiar with them. For now, you just need to test how the registration process works. To include a template part in a top-level template, you must use the Template Part block. The basic markup for this block is: ```markup ``` So open one of the template files from your theme’s `/templates` folder. Your theme should at least have an `index.html` template there, but you can test with any file. Now add the calls to the `wp:template-part` block as shown here: ```markup ``` Now you should be able to see both the Header and Footer template parts if you open the top-level template you added them to via **Appearance > Editor > Templates** in your WordPress admin: [![WordPress Site Editor with a template being edited. The Header template part is selected.](https://i0.wp.com/developer.wordpress.org/files/2023/09/template-parts-include.jpg?resize=2048%2C1071&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/09/template-parts-include.jpg?ssl=1) --- # Style Variations Source: https://developer.wordpress.org/themes/global-settings-and-styles/style-variations/ Unlike most things here in the Global Settings and Styles documentation, style variations are not things you define within `theme.json`. Instead, they are “variations” to your existing `theme.json` file that you can offer to users. A more accurate name for this feature might be *Global Settings and Styles Variations*. Or simply `theme.json` variations. ## What are style variations? Style variations are essentially alternative versions of `theme.json` that you can ship with your theme. They are custom-named JSON files that are stored in your theme’s `/styles` folder. Any [setting](https://developer.wordpress.org/themes/global-settings-and-styles/settings) or [style](https://developer.wordpress.org/themes/global-settings-and-styles/styles) that you can add to `theme.json` can also be added to your style variation JSON file. This lets your users pick and choose which variation they want to use on their site. In a way, they are “skins” for your theme. For example, suppose you’ve created a restaurant theme and have kept the colors and typography pretty basic so that it covers a lot of different restaurant site designs. Further suppose that you wanted to offer more variety, variations on that initial design. You could create a style variation that caters more toward seafood restaurants with fun fonts and an ocean-oriented color palette. Or maybe you want to set the mood for coffee shops that might be running your theme. That’s where style variations can really shine. You can bundle each of these alternative designs for your theme and let your users decide which is the best option for their site. Here is a look at the style variations that are bundled with the default Twenty Twenty-Three theme: [![WordPress Site Editor > Styles sub-screen, which is showing a grid of style variations with a red one in the preview panel.](https://i0.wp.com/developer.wordpress.org/files/2023/09/tt3-style-variations.jpg?resize=2048%2C1071&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/09/tt3-style-variations.jpg?ssl=1)When a user selects a style variation, the JSON data is migrated to the site’s database and stored as a user customization. This allows the data to overrule the theme’s primary `theme.json` settings and styles. ## Adding custom style variations The style variations feature is relatively straightforward if you already understand how `theme.json` works, but there are a couple of differences. The first difference between `theme.json` and style variations are their names and placement in your theme’s folder structure. `theme.json` lives in the root of your theme folder and is considered the default variation. But custom variations must have a unique filename and be placed in the `/styles` folder. Let’s assume you’ve built that restaurant theme mentioned earlier in this document. Now you want to add a couple of variations named Swashbuckler (for that seafood design) and Latte (for the coffee shop design). This is how your theme files would be organized: ``` /your-theme-folder /styles /latte.json /swashbuckler.json /theme.json ``` Style variations are simply variations of `theme.json`, so you have full access to everything in the `theme.json` specification at your fingertips. The second difference between `theme.json` and style variations is the variation title. You can configure this by adding the `title` property to your custom JSON files. Building off the Latte variation example above, you would open your `/styles/latte.json` file and add it, as shown in this code snippet: ```json { "version": 2, "title": "Latte", "settings": {}, "styles": {} } ``` The `title` field is used to represent your variation in the user interface. It is not a required field (WordPress will fall back to your variation), but it does make for a nicer user experience. ## Style variations vs. child themes If you are familiar with the concept of [child themes](https://developer.wordpress.org/themes/advanced-topics/child-themes/), which are covered in the [Advanced Topics](https://developer.wordpress.org/themes/advanced-topics/) documentation, you may be wondering what the differences between them and style variations are. The most obvious difference is that a style variation is limited to a single JSON file that overrides the primary `theme.json`, whereas a child theme can override anything from its parent theme. So it’s probably better to look at the one area they are similar: the JSON file itself. In a child theme, the `theme.json` simply overrides its parent’s `theme.json` file. In a style variation—and this is where the major difference occurs—the variation’s JSON file overrides the `theme.json` file and **its data is saved to the database**. Once a user selects a style variation of a theme, everything in the variation’s JSON file is treated as a user customization. Essentially, WordPress stores that **initial** data in the same way as if the user had simply designed the colors, typography, spacing, etc. from the interface. This is an important distinction to make because it means that when you update a style variation in a future theme release, the user will not receive those changes if they have already saved the style variation. It is possible for users to switch to a variation and switch back to the one they were using to get the update. Style variations can be a great feature to add to your theme, but they have a specific use case. Sometimes child themes make more sense. --- # Appearance Tools Source: https://developer.wordpress.org/themes/global-settings-and-styles/settings/appearance-tools/ `settings.appearanceTools` is a unique property in `theme.json` that behaves as a catchall for multiple other properties. Compared to other settings that you can configure, this one makes it easy to enable several design-related settings in one go. ## Opting into appearance tools `settings.appearanceTools` enables several features related to the design or the *appearance* of a site. By default, the value is set to `false`, so if you choose to not use this property, you can simply not add it to your `theme.json`. However, if you want to enable it, you can set it to `true`: ```json { "version": 2, "settings": { "appearanceTools": true } } ``` This is the equivalent of setting these properties individually in `theme.json`: ```json { "version": 2, "settings": { "border": { "color": true, "radius": true, "style": true, "width": true }, "color": { "link": true }, "dimensions": { "minHeight": true }, "position": { "sticky": true }, "spacing": { "blockGap": true, "margin": true, "padding": true }, "typography": { "lineHeight": true } } } ``` As you can see, it can be a major time-saver and create much less work for you. With `settings.appearanceTools` enabled, you can skip setting those properties individually. You can learn more about what each does via its documentation here in the handbook: - [Border](https://developer.wordpress.org/themes/global-settings-and-styles/border) - [Color](https://developer.wordpress.org/themes/global-settings-and-styles/color) - [Dimensions](https://developer.wordpress.org/themes/global-settings-and-styles/dimensions) - [Position](https://developer.wordpress.org/themes/global-settings-and-styles/position) - [Spacing](https://developer.wordpress.org/themes/global-settings-and-styles/spacing) - [Typography](https://developer.wordpress.org/themes/global-settings-and-styles/typography) ## Overwriting appearance tools Just because you’ve enabled `appearanceTools` doesn’t mean that you cannot disable some features. You can do both. Suppose that you wanted to enable all appearance tools but disable sticky positioning. You would use this code in your `theme.json` to do this: ```json { "version": 2, "settings": { "appearanceTools": true, "position": { "sticky": false } } } ``` This gives you the best of both worlds. You can use `appearanceTools` to enable a large selection of settings but disable others on a case-by-case basis. ## Should I enable appearance tools? There is one caveat to setting `appearanceTools` to `true` in your `theme.json` file: it can automatically opt your theme into design tools in the future. Sometimes, WordPress enables new features when this setting is enabled. Because no one can reliably predict the future, you need to decide whether you want your theme to support unknown design features that you haven’t tested today. For many publicly-distributed themes, this will not typically be an issue if you want to provide a lot of flexibility for your theme’s users. By enabling `appearanceTools`, you can give users new design features without updating your theme. For agencies and freelancers, this could create issues for your clients. Often, these projects are meant to limit the user interface to only specific design tools that the client needs. If WordPress adds new appearance tools in a future update, it’s possible the client will see new and unfamiliar features. For this reason, leaving `appearanceTools` disabled will often make sense. --- # Border Source: https://developer.wordpress.org/themes/global-settings-and-styles/settings/border/ The `settings.border` property in `theme.json` gives you control over the global border settings for blocks in WordPress. It’s important to note that this lets you configure the available settings in the user interface, not the border styles themselves. Each of the border settings maps to a control at the individual block level and in the **Styles** interface for blocks, letting you curate which controls are available to your theme users: [![WordPress post editor showing a Post Featured Image block with custom border settings.](https://i0.wp.com/developer.wordpress.org/files/2023/10/border-settings.jpg?resize=2048%2C1066&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/10/border-settings.jpg?ssl=1)## Border settings WordPress supports four border settings that you can configure via the `settings.border` property in `theme.json`. Each of them allows you to enable or disable a specific border feature and accepts a boolean (`true` or `false`) value: - **`color`:** Enables/Disables the border-color picker. - **`radius`:** Enables/Disables the border-radius control. - **`style`:** Enables/Disables the border-style selector (users have the option of `solid`, `dashed`, or `dotted`). - `width`: Enables/Disables the border-width input. By default, all border properties are set to `false`, as shown in this example `theme.json` code: ```json { "version": 2, "settings": { "border": { "color": false, "radius": false, "style": false, "width": false } } } ``` As of WordPress 6.3, `color`, `style`, and `width` are intertwined. If any one of them is set to `true`, the others will be available as options within the user interface. Also, setting the `radius` option to `false` does not work for the Button block. The border-radius control in the editor always appears. --- # Color Source: https://developer.wordpress.org/themes/global-settings-and-styles/settings/color/ Color is one of the primary components of design. You can create a theme that is dark and moody, fun and lighthearted, or clean and corporate. Which colors you choose will define how the world sees your theme, and WordPress provides a range of color-specific configuration options that you can set. The `settings.color` property in `theme.json` gives you full control over how colors, gradients, and more work within your theme. Primarily, the goal is for configuring whether specific controls appear in the user interface, but it also lets you register custom presets that users can select. ## Color settings `color` is an object that’s nested directly within the top-level `settings` property in `theme.json`. It is used to configure multiple color-specific settings that appear in the user interface. Take a look at the `color` property in the context of a `theme.json` file with its default values: ```json { "version": 2, "settings": { "color": { "background": true, "custom": true, "customDuotone": true, "customGradient": true, "defaultDuotone": true, "defaultGradients": true, "defaultPalette": true, "duotone": [], "gradients": [], "link": true, "palette": [], "text": true } } } ``` As you can see, most of the settings accept a boolean value, meaning that you can set them to either `true` or `false`. Others, like `duotone`, `gradients`, and `palette` take an array of values. These are the ones where you can register custom presets, and you will learn how to create them in this doc. Color settings can largely be broken down into four groups that let you: - Enable or disable settings in the UI. - Enable or disable user customizations of colors, duotones filters, and gradients. - Enable or disable the core WordPress color, duotone, and gradient presets. - Register custom color, duotone, and gradient presets. In the following sections, you will learn how each of these work. ## Text, background, and link settings In the block editor, you will often see **Text**, **Background**, and **Link** settings under the **Color** panel for a block, at least for those blocks that opt into support of one or more of them. These options appear like this in the interface: [![WordPress post editor with a Paragraph block that has a blue background. On the right, the Background color picker is open, revealing various color options.](https://i0.wp.com/developer.wordpress.org/files/2023/10/theme-json-color-options.jpg?resize=2048%2C1066&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/10/theme-json-color-options.jpg?ssl=1)But just because a block registers support for text, background, and link colors doesn’t mean that your theme must also support them. That’s entirely up to you. WordPress lets you decide whether your theme supports any or all of the settings by defining the `background`, `link`, and `text` properties under `settings.color` in `theme.json`: ```json { "version": 2, "settings": { "color": { "background": true, "link": true, "text": true } } } ``` By default, all are set to `true`, so their associated controls will appear in the block interface. If you want to disable a feature, you only need to set its value to `false` in your `theme.json`. For an exercise, try disabling the background color but still allow text and link colors: ```json { "version": 2, "settings": { "color": { "background": false, "link": true, "text": true } } } ``` Some core WordPress blocks and third-party blocks may have other color options that users can configure. These cannot be enabled or disabled via `theme.json` since they are not a standard component of the color system. ## Enabling and disabling user customizations One of the major decisions that you will need to make for your theme is whether you want to allow users to create custom colors. On the one hand, enabling custom colors gives users a ton of flexibility and freedom to truly make their site their own. But maybe you’ve put in a lot of work getting the color scheme *just right* and want to make sure the user is only picking colors from a predetermined palette. This may change depending on whether you are building a publicly-distributed theme vs. one for a client. Each project is unique, and you get to be the judge on what’s best for your design. WordPress currently allows user-customized colors for three different features, which you can enable or disable via `theme.json`: - **`custom`:** Whether the user can create and use custom colors. - **`customDuotone`:** Whether the user can create custom duotone filters (typically used for overlays on blocks with images). - **`customGradient`:** Whether the user can create custom background gradients. By default, each of these features are enabled in `theme.json`: ```json { "version": 2, "settings": { "color": { "custom": true, "customDuotone": true, "customGradient": true } } } ``` ### User-customized colors When the `settings.colors.custom` value is set to `true` (the default), users will be able to define custom colors for individual blocks, as shown here: [![WordPress post editor with a Paragraph block in the editor with a blue background. The Text color option is open and shows a user selecting a custom color.](https://i0.wp.com/developer.wordpress.org/files/2023/10/theme-json-custom-colors.jpg?resize=2048%2C1066&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/10/theme-json-custom-colors.jpg?ssl=1)Because this is enabled by default, try turning it off by setting the property to `false` in your `theme.json` file: ```json { "version": 2, "settings": { "color": { "custom": false } } } ``` Now users will only be able to select from preset colors. ### User-customized duotone filters Duotone filters are generally supported by blocks that display an image. The filter is applied as an overlay above the image, creating a duotone effect. The two-color filter allows users to select a shadow and highlight color. By default, users can create custom duotone filters as shown here: [![WordPress post editor showing an Image block with the custom duotone filters option open.](https://i0.wp.com/developer.wordpress.org/files/2023/10/theme-json-custom-duotone-scaled.jpg?resize=2560%2C1333&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/10/theme-json-custom-duotone-scaled.jpg?ssl=1)Since custom duotone filters are enabled by default, you must set the `settings.color.customDuotone` property to `false` if you do not want to allow users to add custom colors: ```json { "version": 2, "settings": { "color": { "customDuotone": false } } } ``` ### User-customized gradients Like most other color settings, custom gradients are enabled by default. This allows your theme users to define a gradient background for any block that supports it as shown here: [![WordPress post editor with a Cover block shown. In the right sidebar, the gradient picker is open for the Overlay option.](https://i0.wp.com/developer.wordpress.org/files/2023/10/theme-json-custom-gradients.jpg?resize=2048%2C1066&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/10/theme-json-custom-gradients.jpg?ssl=1)If you’ve carefully fine-tuned the gradients you want available to the user or simply want to disable custom gradients altogether, you can turn this feature off by setting `settings.color.customGradient` to `false` in `theme.json`: ```json { "version": 2, "settings": { "color": { "customGradient": false } } } ``` ## Default WordPress presets WordPress creates its own presets for each of the color features. As is the case with user-defined colors, you will need to decide whether you want to give users access to these. They will often clash with your theme’s color palette, but you may also opt to give users complete freedom to decide on their own. WordPress currently allows user-customized colors for three different features, which you can enable or disable via `theme.json`: - `defaultDuotone`: Whether the user can select from WordPress’ default duotone filter presets (typically used for overlays on blocks with images). - **`defaultGradients`:** Whether the user can select from WordPress’ default background gradient presets. - **`defaultPalette`:** Whether the user can select colors from WordPress’ default color palette. By default, each of these features are enabled in `theme.json`: ```json { "version": 2, "settings": { "color": { "defaultDuotone": true, "defaultGradients": true, "defaultPalette": true } } } ``` It’s important to note that, even if these settings are disabled, WordPress will still generate the CSS custom properties for its presets. This is for backward-compatibility and so that users do not lose colors, gradients, or duotone filters that they have previously chosen when using another theme. ### Default color palette WordPress ships with its own color palette, which is enabled by default for themes that have not opted out of it. It contains the following colors: - Black - Cyan bluish gray - White - Pale pink - Vivid red - Luminous vivid orange - Luminous vivid amber - Light green cyan - Vivid green cyan - Pale cyan blue - Vivid cyan blue - Vivid purple Color presets are available for the **Text**, **Background**, **Link**, and potentially other color controls as shown in this screenshot: [![WordPress post editor with a Group block wrapping a Paragraph. The Text color option is highlighted in the right sidebar.](https://i0.wp.com/developer.wordpress.org/files/2023/10/default-colors.jpg?resize=2048%2C1066&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/10/default-colors.jpg?ssl=1)There are times when you might want to disable the core WordPress colors, and you can do so by setting `settings.color.defaultPalette` to `false` in `theme.json`: ```json { "version": 2, "settings": { "color": { "defaultPalette": false } } } ``` ### Default duotone filters WordPress has several default duotone filter presets that it defines: - Dark Grayscale - Grayscale - Purple and yellow - Blue and red - Midnight - Magenta and yellow - Purple and green - Blue and orange These will appear for blocks that support duotone filters (generally used as an overlay for blocks with images), as shown here: [![WordPress post editor with a purple and yellow duotone filter applied to an Image in the content canvas.](https://i0.wp.com/developer.wordpress.org/files/2023/10/default-duotone-filters.jpg?resize=2048%2C1066&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/10/default-duotone-filters.jpg?ssl=1)If you do not want to allow your theme users to select from the default duotone presets, you must set `settings.color.defaultDuotone` to `false` in `theme.json`: ```json { "version": 2, "settings": { "color": { "defaultDuotone": false } } } ``` ### Default gradients By default, WordPress defines several gradients for users to pick and choose from. These can be added to blocks that support gradient backgrounds: - Vivid cyan blue to vivid purple - Light green cyan to vivid green cyan - Luminous vivid amber to luminous vivid orange - Luminous vivid orange to vivid red - Very light gray to cyan bluish gray - Cool to warm spectrum - Blush light purple - Blush bordeaux - Luminous dusk - Pale ocean - Electric grass - Midnight They appear as shown here in the **Background > Gradient** control in the user interface: [![WordPress post editor with a Group block and a purple and orange background gradient selected.](https://i0.wp.com/developer.wordpress.org/files/2023/10/default-gradients.jpg?resize=2048%2C1066&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/10/default-gradients.jpg?ssl=1)The core WordPress gradient presets are enabled by default, but there are times when you may want to disable them for your theme. You can do so by setting `settings.color.defaultGradients` to `false` in your `theme.json`: ```json { "version": 2, "settings": { "color": { "defaultGradients": false } } } ``` ## Registering custom color presets Just like WordPress defines its own color, duotone, and gradient presets, so can you. This is a powerful feature that allows you to customize how your theme looks on the front end of the site and which colors your theme users can select from in the block editor. You can set presets for three different features via `theme.json`: - `duotone`: An array of duotone filters that a user can choose from (typically used for overlays on blocks with images). - `gradients`: An array of background gradient objects that a user can choose from. - **`palette`:** An array of color objects that a user can choose from. Here is what this would look like in `theme.json` (note that there are no presets yet registered): ```json { "version": 2, "settings": { "color": { "duotone": [], "gradients": [], "palette": [] } } } ``` WordPress will automatically generate CSS custom properties for each of your presets in the form of `--wp--preset--{type}--{slug}`. So a color palette preset with the slug of `contrast` will become `--wp--preset--color--contrast`. You can access these in your `theme.json` styles via the CSS custom property itself or through a special naming convention of `var:preset|{type}|{slug}`. You will learn more about this in the `theme.json` [Styles documentation](https://docs.google.com/document/d/1jFI5wPr3cjaac4xDaH7OIwc5QqDo1OAGNHt23zR7Sb4/edit#). WordPress will also sometimes generate CSS classes based on the preset. For example, the `contrast` color palette preset will have an associated class for `.has-contrast-color` when used as a block’s text color and `.has-contrast-background-color` when used as a background. ### Custom color palette When building a theme you will almost always want to register your own color palette. For some themes, this may be as simple as a couple of colors. Others could potentially include dozens of colors. In the end, it’s your theme, and WordPress gives you the tools to build your design. You can register custom colors via the `settings.color.palette` property in `theme.json`: ```json { "version": 2, "settings": { "color": { "palette": [] } } } ``` The `palette` property accepts an array of color objects, and each of those objects has three properties that you must set: - `color`: A valid CSS color value. - **`name`:** The label for your color, which will be internationalized (so that it can be translated) and shown to the user in some contexts, such as tooltips. - **`slug`:** A unique machine-readable slug/ID for your color. This is used to generate CSS custom properties and CSS classes. Suppose you wanted to register three colors named Base, Contrast, and Primary for your theme. They would appear in the color picker like so: [![WordPress post editor showing a Group block around a Paragraph. The Group has a thick blue border and black text selected.](https://i0.wp.com/developer.wordpress.org/files/2023/10/theme-color-palette.jpg?resize=2048%2C1066&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/10/theme-color-palette.jpg?ssl=1)For your custom colors to appear in the interface, you must add them to the `settings.color.palette` array as shown in this code snippet: ```json { "version": 2, "settings": { "color": { "palette": [ { "color": "#ffffff", "name": "Base", "slug": "base" }, { "color": "#000000", "name": "Contrast", "slug": "contrast" }, { "color": "#89CFF0", "name": "Primary", "slug": "primary" } ] } } } ``` You can add as few or as many colors as you want, and there are no official naming schemes. Despite there not being an official naming scheme for colors, the `base` and `contrast` slugs are *de facto* standards [that were set forth](https://github.com/WordPress/Documentation-Issue-Tracker/issues/563) by the Twenty Twenty-Three default theme. It is recommended to use `base` for the site background and `contrast` for text. This provides the greatest future-proofing and compatibility between themes. It also gives plugin authors a standard set of fallback colors when needed. ### Custom gradients Like colors, you can also register a custom set of gradient presets. And there are no limits on the number of gradients your theme can support, so go wild and have a bit of fun! You can register custom gradients via the `settings.color.gradients` property in `theme.json`: ```json { "version": 2, "settings": { "color": { "gradients": [] } } } ``` The `gradients` property accepts an array of gradient objects, and each of those objects has three properties that you must set: - **`gradient`:** A valid CSS background gradient value. - **`name`:** The label for your gradient, which will be internationalized (so that it can be translated) and shown to the user in some contexts, such as tooltips. - **`slug`:** A unique machine-readable slug/ID for your gradient. This is used to generate CSS custom properties and CSS classes. Let’s suppose you have a couple of gradients named Emerald and Fabled Sunset that you want to add for your theme as shown here: [![WordPress post editor with a Group block that has a Purple to Yellow gradient background.](https://i0.wp.com/developer.wordpress.org/files/2023/10/theme-gradients.jpg?resize=2048%2C1066&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/10/theme-gradients.jpg?ssl=1)Add the following to your `theme.json` to register them: ```json { "version": 2, "settings": { "color": { "gradients": [ { "gradient": "linear-gradient(to right, #10b981, #64a30d)", "name": "Emerald", "slug": "emerald" }, { "gradient": "linear-gradient(-225deg,#231557,#44107a 29%,#ff1361 67%,#fff800)", "name": "Fabled Sunset", "slug": "fabled-sunset" } ] } } } ``` ### Custom duotone filters Like colors and gradients, you can register any number of custom duotone filters for your theme. This will allow your users to apply customizations directly to Image and other blocks that support duotone. You can register custom gradients via the `settings.color.duotone` property in `theme.json`: ```json { "version": 2, "settings": { "color": { "duotone": [] } } } ``` The `duotone` property accepts an array of duotone objects, and each of those objects has three properties that you must set: - **`colors`:** An array containing two valid CSS color values. - **`name`:** The label for your duotone filter, which will be internationalized (so that it can be translated) and shown to the user in some contexts, such as tooltips. - **`slug`:** A unique machine-readable slug/ID for your duotone filter. This is used to generate CSS custom properties and CSS classes. Suppose you wanted to create to create two duotone filters—one for red shadows and highlights and a similar one for blues, as shown below: [![WordPress post editor with a blue-tinted duotone filter applied to an Image block.](https://i0.wp.com/developer.wordpress.org/files/2023/10/theme-duotone-filters.jpg?resize=2048%2C1066&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/10/theme-duotone-filters.jpg?ssl=1)To register the Red and Blue dutone filters, add this code to your `theme.json`: ```json { "$schema": "https://schemas.wp.org/trunk/theme.json", "version": 2, "settings": { "color": { "duotone": [ { "colors": [ "#450a0a", "#fef2f2" ], "name": "Red", "slug": "red" }, { "colors": [ "#172554", "#eff6ff" ], "name": "Blue", "slug": "blue" } ] } } } ``` Duotone does not currently support CSS custom properties or references and cannot be dynamically generated. There is an [open ticket](https://github.com/WordPress/gutenberg/issues/33905) to solve this issue. --- # Custom Source: https://developer.wordpress.org/themes/global-settings-and-styles/settings/custom/ The `settings.custom` property is unique among other settings in `theme.json`. As its name implies, it is a custom property. This means that you get to decide how to use it. Essentially, it provides a method for creating CSS custom properties that you might need elsewhere in your theme. In this document, you will learn what the `custom` property is for and how you can use it in your theme. ## Overview of the custom setting The `settings.custom` property accepts a single object, and this object can be used to store other values. The individual object values must be valid CSS values or an object with nested key/value pairs. Here is an example snippet from `theme.json` with no custom values set: ```json { "version": 2, "settings": { "custom": {} } } ``` The great thing about the `settings.custom` object is that you can use it to create your own CSS custom properties. When you add a key and value to the object, WordPress will automatically generate the CSS custom property, assign the value, and load it for you. The generated CSS custom property will follow this pattern: `--wp--custom--{key}--{value}`. Suppose you wanted to use the key of `fruit` and give it a value of `apple`. Add this to your `theme.json` file: ```json { "version": 2, "settings": { "custom": { "fruit": "apple" } } } ``` WordPress will then generate this CSS: ```css body { --wp--custom--fruit: apple; } ``` ## How CSS custom properties are generated As you learned above, the `settings.custom.fruit` key name will generate the `--wp--custom--fruit` variable in CSS. But there are other cases too. ### Automatic hyphenation WordPress will automatically hyphenate camel-cased names. For example, `lineHeight` in the following example will become `line-height`: ```json { "version": 2, "settings": { "custom": { "lineHeight": "1.4em" } } } ``` This will create the following CSS: ```css body { --wp--custom--line-height: 1.4em; } ``` Numbers are handled the same as uppercase letters when used as a key. For example, a key of `abc123` will become `abc-1-2-3` in the resulting CSS. ### Nested properties Building off the above example, suppose you wanted to create several line-height CSS custom properties for use in your theme. For this, you might want to create an object under `settings.custom.lineHeight` instead of a single value. Add the following to your `theme.json` file: ```json { "version": 2, "settings": { "custom": { "lineHeight": { "xs": "1", "sm": "1.25", "md": "1.5", "lg": "1.75" } } } } ``` WordPress will automatically use this nested structure when generating the CSS custom property names. This will generate this CSS: ```css body { --wp--custom--line-height--xs: 1; --wp--custom--line-height--sm: 1.25; --wp--custom--line-height--md: 1.5; --wp--custom--line-height--lg: 1.75; } ``` There is no limit to the amount of nesting you can do, but keep in mind that the more you nest, the longer your CSS custom property names become. ## Practical usage What you use the `settings.custom` property for is entirely up to you. At its core, all it really does is generate CSS custom properties, which don’t do anything on their own. Custom properties must also be used in CSS. In the previous `theme.json` example above, you created a set of line-heights. There are a number of ways you can put these into practical use. ### Use in theme.json styles In the [Styles documentation](https://developer.wordpress.org/themes/global-settings-and-styles/styles), you will learn how to apply styles to the root element, elements, and blocks via `theme.json`. This will be one of the primary use cases for integrating with `settings.custom`. Suppose you wanted to register the same set of line-heights from above and make use of them. Maybe you want to set the root element to the `md` line-height and Paragraph blocks to `lg`. You can access each line-height property via `var:custom|line-height|md` and `var:custom|line-height|lg`, respectively. Use this code in your `theme.json` file: ```json { "version": 2, "settings": { "custom": { "lineHeight": { "xs": "1", "sm": "1.25", "md": "1.5", "lg": "1.75" } } }, "styles": { "typography": { "lineHeight": "var:custom|line-height|md" } "blocks": { "core/paragraph": { "typography": { "lineHeight": "var:custom|line-height|lg" } } } } } ``` You can also reference the values via their CSS custom properties. For example, instead of using `var:custom|line-height|md`, use `var( --wp--custom--line-height--md )`. Remember, you will learn more about styling via `theme.json` from the [Styles documentation](https://developer.wordpress.org/themes/global-settings-and-styles/styles/). You can use what you learn there to combine with the techniques outlined here. ### Use in CSS There are times when you might need to reference the generated CSS custom properties directly in CSS, such as your `style.css` file. To do this, you must use the CSS custom property name. Suppose you needed to target a class with the name of `.example-class` and to give it the `sm` line-height that you’ve registered. Use this code in your CSS: ```css .example-class { line-height: var( --wp--custom--line-height--sm ); } ``` --- # Dimensions Source: https://developer.wordpress.org/themes/global-settings-and-styles/settings/dimensions/ The `settings.dimensions` property in `theme.json` gives you control over the global dimensions settings for blocks. This property lets you decide which dimension controls are available in the user interface. In this document, you will learn what the `dimensions` property is for and how you can use it in your theme. ## Dimensions settings `dimensions` is an object that’s nested directly within the top-level `settings` property in `theme.json`. Currently, it only lets you set a single property: - **`minHeight`:** A boolean value for enabling block support for the **Minimum Height** control. Take a look at the `dimensions` property in the context of a `theme.json` file with its default values: ```json { "version": 2, "settings": { "dimensions": { "minHeight": false } } } ``` ### Minimum Height The `settings.dimensions.minHeight` property lets you control whether the **Minimum Height** field appears for blocks that have opted into support for the feature. As of WordPress 6.3, the only core WordPress blocks that do are Group and Post Content. To enable support for the control, you must set the property’s value to `true` in `theme.json`: ```json { "version": 2, "settings": { "dimensions": { "minHeight": true } } } ``` This will enable the control in the interface. As shown in this screenshot, the **Minimum Height** field appears for the Group block (Stack variation): [![WordPress post editor with a Stack block in the content canvas. Its minimum height is set in the sidebar.](https://i0.wp.com/developer.wordpress.org/files/2023/10/group-min-height.jpg?resize=2048%2C1066&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/10/group-min-height.jpg?ssl=1) --- # Layout Source: https://developer.wordpress.org/themes/global-settings-and-styles/settings/layout/ The `settings.layout` property in `theme.json` is an object that stores layout-related settings that you can configure. At the moment, it is used for setting “content” and “wide” widths, but it could also be used for other settings in the future. In this document, you will learn what the `layout` property is used for and how you can use it in your theme. ## Layout settings `layout` is an object that’s nested directly within the top-level `settings` property in `theme.json`. Within that object, you can define two settings: - `contentSize`: A valid CSS length value for defining the default width for content. It is typically used for controlling the width of the post content and related areas on the page. - **`wideSize`:** A valid CSS length value for defining the default wide alignment width, which is generally between the content size and full viewport width. Take a look at the `layout` property in the context of a `theme.json` file with its default values: ```json { "version": 2, "settings": { "layout": { "contentSize": "", "wideSize": "" } } } ``` ### Content size The `settings.layout.contentSize` property is primarily useful for defining the width of a site’s content area. Think of this as the default width of your site. You can break outside of this by applying the “wide” (below) or “full” width to a block. The content width is merely the foundation. In almost any design, you will want to limit this width to something that is comfortable to read, especially if the content is going to include text. This is a value that you will need to determine for yourself, but a good rule of thumb is that you should have 45-75 characters of text per line (though some guidelines differ slightly on the number range). Of course, your default font-family and font-size are crucial pieces to figuring this out. Try configuring a content size in your `theme.json` file: ```json { "version": 2, "settings": { "layout": { "contentSize": "40rem" } } } ``` If you open a template in the **Site Editor**, you can use it to define the layout for various blocks. In the screenshot below, you can see that the Post Content block has the **Inner blocks use content width** option selected under the **Layout** tab: [![WordPress post editor with a Post Content block selected, showing its inner content limited to the content width.](https://i0.wp.com/developer.wordpress.org/files/2023/10/content-size.jpg?resize=2048%2C1066&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/10/content-size.jpg?ssl=1)What this setting does is tell WordPress that any nested blocks within the Post Content block should be set to the `40rem` value defined for `settings.layout.contentSize` in `theme.json`. ### Wide Size The `settings.layout.wideSize` property defines a width for “wide” blocks. To be useful, wide blocks must be nested within a block that is telling WordPress that its inner blocks should be limited to the “content” size. Wide-aligned blocks are meant to “break outside” of their parent block. Not every theme will benefit by having a wide size. Depending on the design, a theme’s layout may simply not have additional room for blocks to break out of their container. In those cases, you do not need to set this value. For theme designs that can accommodate wide blocks (typical of sidebar-less designs), you will want to set this to a value that is greater than `settings.layout.contentWidth`. But it shouldn’t stretch to the width of the full screen (e.g., `100vw`). WordPress has a separate full-width setting that you can use for that. Try adding a custom `settings.layout.wideSize` to your `theme.json` file (remember, you need a set content size for this to be useful): ```json { "version": 2, "settings": { "layout": { "contentSize": "40rem", "wideSize": "64rem" } } } ``` Now open your **Site Editor** in the WordPress admin and edit a template. First, add a **Group** block with the **Inner blocks use content width** option enabled. Then, stick another block within it and select the **Wide width** option. In the screenshot below, you can see the Post Featured Image block nested within a Group block. It breaks out of its parent container but the other post-related blocks are limited to the content width: [![WordPress site editor with the Post Featured Image block selected and set to "wide width".](https://i0.wp.com/developer.wordpress.org/files/2023/10/wide-size.jpg?resize=2048%2C1066&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/10/wide-size.jpg?ssl=1) --- # Lightbox Source: https://developer.wordpress.org/themes/global-settings-and-styles/settings/lightbox/ `settings.lightbox` is a specific setting that you can enable for supported blocks. It enables a lightbox feature that expands an image when a site visitor clicks on an image. This setting is only available as of WordPress 6.4 and is specific to the core Image block (`core/image`). ## Lightbox settings The `lightbox` setting is specific to the Image block, so the following examples will be shown in that context. The `lightbox` property is an object that has two nested properties that you can configure: - **`enabled`:** Whether to enable the lightbox feature for the Image block. The default value is `undefined` (the equivalent of being disabled). - **`allowEditing`:** Whether to show the **Expand on click** option in the interface, which allows the user to enable/disable lightbox for individual images. Defaults to `true`. Here is a look at the default `theme.json`: ```json { "version": 2, "settings": { "blocks": { "core/image": { "lightbox": { "allowEditing": true } } } } } ``` ### Enabling lightbox for images To enable the lightbox feature for Image blocks used throughout the site, you must set `settings.blocks.core/image.lightbox.enabled` to true in `theme.json`: ```json { "version": 2, "settings": { "blocks": { "core/image": { "lightbox": { "enabled": true } } } } } ``` On the front-end of the site, visitors will be able to expand the image when clicking on it. The image will then overlay the entire screen (including an **x** button for closing the overlay), as shown below: [![Image of palm trees expanded as an overlay modal.](https://i0.wp.com/developer.wordpress.org/files/2023/10/lightbox-expanded.jpg?resize=2048%2C959&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/10/lightbox-expanded.jpg?ssl=1)### Disabling user editing By default, WordPress will show an **Expand on Click** option under the **Settings** tab for the Image block: [![WordPress post editor with an Image block showing the "expand on click" option selected.](https://i0.wp.com/developer.wordpress.org/files/2023/10/lightbox-allow-editing.jpg?resize=2048%2C1056&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/10/lightbox-allow-editing.jpg?ssl=1)This control allows your theme’s users to enable or disable the lightbox feature on a per-block basis. To disallow user editing, you must set `settings.blocks.core/image.lightbox.allowEditing` to `false` in `theme.json`: ```json { "version": 2, "settings": { "blocks": { "core/image": { "lightbox": { "allowEditing": false } } } } } ``` --- # Position Source: https://developer.wordpress.org/themes/global-settings-and-styles/settings/position/ The `settings.position` property in `theme.json` gives you control over the global positioning settings for blocks in WordPress. It’s important to note that this lets you configure the available settings in the user interface, not the position styles. ## Position settings `position` is an object that’s nested directly within the top-level `settings` property in `theme.json`. Currently, it only lets you set a single property: - **`sticky`:** A boolean value for enabling block support for the **Position: Sticky** option. Take a look at the `position` property in the context of a `theme.json` file with its default values: ```json { "version": 2, "settings": { "position": { "sticky": false } } } ``` ### Enabling sticky positioning Sticky positioning can be particularly useful in theme designs that feature a header that sticks to the top of the screen as the user scrolls down the page. This is one of the primary use cases, but it can also be useful in other scenarios. Setting a block to the sticky position will stick the block to its most immediate parent when the user scrolls the page. Sticky positioning is only possible if enabled in `theme.json`. To enable sticky positioning for blocks that support it, set `settings.position.sticky` to `true`: ```json { "version": 2, "settings": { "position": { "sticky": true } } } ``` This will enable a new **Position** tab in the block inspector controls (for blocks that support the position feature, such as Group). The control will show a dropdown select with the available position options: **Default** and **Sticky**: [![WordPress site editor with the Header template part selected. In the right sidebar, the Sticky option is selected for the Position setting.](https://i0.wp.com/developer.wordpress.org/files/2023/10/position-sticky-header.jpg?resize=2048%2C1066&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/10/position-sticky-header.jpg?ssl=1) If you want to create a sticky header, note that you cannot use positioning on the Header template part. You must wrap it with a containing Group block and apply the sticky positioning to the Group. --- # Shadow Source: https://developer.wordpress.org/themes/global-settings-and-styles/settings/shadow/ The `settings.shadow` property in `theme.json` currently lets you create custom shadow presets. As of WordPress 6.3, it contains no settings for enabling or disabling UI elements. Shadow, in this case, refers specifically to the `box-shadow` CSS feature and is unrelated to `text-shadow`. ## Shadow settings The `settings.shadow` property contains two settings that you can configure: - **`defaultPresets`:** A boolean value for enabling or disabling the default WordPress shadow presets. Defaults to `true`. - `presets`: An array of objects for registering custom shadows for use in your theme or by users. Here is a look at the default shadow property in `theme.json`: ```json { "version": 2, "settings": { "shadow": { "defaultPresets": true, "presets": [ { "name": "Natural", "slug": "natural", "shadow": "6px 6px 9px rgba(0, 0, 0, 0.2)" }, { "name": "Deep", "slug": "deep", "shadow": "12px 12px 50px rgba(0, 0, 0, 0.4)" }, { "name": "Sharp", "slug": "sharp", "shadow": "6px 6px 0px rgba(0, 0, 0, 0.2)" }, { "name": "Outlined", "slug": "outlined", "shadow": "6px 6px 0px -3px rgba(255, 255, 255, 1), 6px 6px rgba(0, 0, 0, 1)" }, { "name": "Crisp", "slug": "crisp", "shadow": "6px 6px 0px rgba(0, 0, 0, 1)" } ] } } } ``` As you can see, WordPress registers several default presets that you can use directly in your block styles or that users can select from the interface: - Natural - Deep - Sharp - Outline - Crisp Like all presets, WordPress will generate a CSS custom property for each registered shadow. Shadow presets are named `--wp--preset--shadow--{$slug}`. Here is an example of the CSS generated for the default shadow presets: ```css body { --wp--preset--shadow--natural: 6px 6px 9px rgba(0, 0, 0, 0.2); --wp--preset--shadow--deep: 12px 12px 50px rgba(0, 0, 0, 0.4); --wp--preset--shadow--sharp: 6px 6px 0px rgba(0, 0, 0, 0.2); --wp--preset--shadow--outlined: 6px 6px 0px -3px rgba(255, 255, 255, 1), 6px 6px rgba(0, 0, 0, 1); --wp--preset--shadow--crisp: 6px 6px 0px rgba(0, 0, 0, 1); } ``` ## Disabling core WordPress shadows The default shadows available in core will not match the design of every theme. Typically, they will only work well for themes with a white or very light gray background. If your theme uses a different color, you will almost always want to remove these. But there may be other reasons to disable the defaults. Perhaps you want to limit users to only the shadows that you’ve specifically designed for your theme or simply not like their design. Whatever the reason, you can remove them by setting `settings.shadow.defaultPresets` to `false` in `theme.json`: ```json { "version": 2, "settings": { "shadow": { "defaultPresets": false } } } ``` ## Adding custom shadow presets WordPress lets you register any number of custom shadows. You can add them via the `settings.shadow.presets` property, which is an array used for storing shadow objects. Each object in this array should contain three values: - **`name`:** A human-readable name or label for the shadow that can be translated. - **`slug`:** A machine-readable slug for the shadow, which is used to build its associated CSS custom property. - **`shadow`:** A valid CSS value for the `box-shadow` CSS property. Try your hand at registering a few shadows of your own. You can use this `theme.json` code to get started, which contains several shadow examples: ```json { "$schema": "https://schemas.wp.org/trunk/theme.json", "version": 2, "settings": { "shadow": { "presets": [ { "name": "Small", "slug": "sm", "shadow": "0 1px 2px 0 rgb(0 0 0 / 0.05)" }, { "name": "Medium", "slug": "md", "shadow": "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)" }, { "name": "Large", "slug": "lg", "shadow": "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)" }, { "name": "XL", "slug": "xl", "shadow": "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)" }, { "name": "2XL", "slug": "2-xl", "shadow": "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)" }, { "name": "Inner", "slug": "inner", "shadow": "inset 0 2px 4px 0 rgb(0 0 0 / 0.05)" } ] } } } ``` Currently, this only shows a shadow option for the core Button block in the user interface. This control can be accessed via **Appearance > Editor > Styles > Style Book** in the WordPress admin. From there, select the **Button** block and locate the **Shadow** option in the **Effects** tab, as shown here: [![WordPress Style Book screen with the Button block highlighted. It has a gray drop-shadow.](https://i0.wp.com/developer.wordpress.org/files/2023/10/shadow-ui-buttons.jpg?resize=2048%2C1066&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/10/shadow-ui-buttons.jpg?ssl=1)It’s possible for third-party blocks to also utilize shadow presets and show them in the interface in the post, template, or site editors. Like other presets, you can also use your custom shadows (or core WordPress shadows) in [`theme.json` Styles](https://developer.wordpress.org/themes/global-settings-and-styles/styles). For a deeper dive into this feature, read [Using the box-shadow feature for themes](https://developer.wordpress.org/news/2023/01/using-the-box-shadow-feature-for-themes/) on the WordPress Developer Blog. --- # Spacing Source: https://developer.wordpress.org/themes/global-settings-and-styles/settings/spacing/ Spacing is one of the most complex parts of web design. It involves combining things like margin, padding, gap, line height, font size, and more into a harmonious flow. Doing this well requires a keen eye and a foundational understanding of how each of these pieces come together. The `settings.spacing` property in `theme.json` covers settings related specifically to margin, padding, and gap. This handbook also has documentation for [typography settings](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography) and [applying styles](https://developer.wordpress.org/themes/global-settings-and-styles/styles) to blocks, both of which play roles in wrangling the spacing for your overall design. ## Spacing settings The `settings.spacing` object has several properties that you can configure: - **`blockGap`:** Whether to enable the **Block Spacing** option for blocks that support it. Can be a boolean value (`true`/`false`). Defaults to `null`. If set to null, WordPress’ generated CSS is also disabled. - **`margin`:** Whether to enable the **Margin** option for supported blocks. Defaults to `false`. - **`padding`:** Whether to enable the **Padding** option for supported blocks. Defaults to `false`. - **`customSpacingSize`:** Whether to allow users to input custom spacing values for supported blocks. Defaults to `true`. - **`spacingScale`:** A configuration object for defining a custom spacing scale. WordPress defines a default scale with seven steps that increment by `1.5rem`. - **`spacingSizes`:** An array of custom size objects that may overrule the spacing scale or add to it. - **`units`:** An array of possible CSS units that users can select from when adding custom spacing. Here is what spacing settings look like the default WordPress `theme.json`: ```json { "version": 2, "settings": { "spacing": { "blockGap": null, "customSpacingSize": true, "margin": false, "padding": false, "spacingScale": { "operator": "*", "increment": 1.5, "steps": 7, "mediumStep": 1.5, "unit": "rem" }, "spacingSizes": [], "units": [ "px", "em", "rem", "vh", "vw", "%" ] } } } ``` ## Enabling or disabling spacing options As noted in the default settings in the previous section, there are several settings that are merely for enabling or disabling elements in the user interface. In this section, you will learn how to configure each of these. ### Enabling block spacing (block gap) In WordPress, the “block gap” refers to the spacing between blocks on a page. In most cases, this is the vertical spacing between blocks. But it can also refer to horizontal spacing when blocks are set in horizontal flex or in a grid layout. In flow layouts (the default), the block gap is applied using the CSS `margin-top` property to sibling elements. In flex or grid layouts, it is applied using the CSS `gap` property. WordPress will automatically output the CSS for the block gap if this setting is not disabled entirely (the default). You will learn more about defining block gap styles in the [Styles documentation](https://developer.wordpress.org/themes/global-settings-and-styles/styles), but having a baseline understanding of the terminology should help you decide how to work with this option. The primary purpose of the `settings.spacing.blockGap` is to enable or disable the user interface for the **Block Spacing** control for blocks that support it. You can do this by setting it to `true` or `false`. However, you can also leave it as `null` (the default value). This disables the user interface. In addition, it removes the WordPress-generated block spacing CSS. Leaving this to the default `null` value is not usually recommended except in special cases. Generally, you would want consistent spacing as part of your design’s vertical rhythm. If set to `null`, you will need to handle that manually via custom CSS. Use this table as a reference when determining which value to assign to `settings.spacing.blockGap`: | `blockGap` Value | Block Spacing Control | WordPress-generated CSS | |---|---|---| | `null` | No | No | | `true` | Yes | Yes | | `false` | No | Yes | Now try configuring the setting. Open your `theme.json` file and set the property to `true`: ```json { "version": 2, "settings": { "spacing": { "blockGap": true } } } ``` For blocks that support the property, you should now see the **Block Spacing** control appear. Here is a screenshot of what that looks like on the Post Template block: [![WordPress editor with a Query Loop block. In the sidebar, the Block Spacing dropdown is open.](https://i0.wp.com/developer.wordpress.org/files/2023/10/block-gap-post-template.jpg?resize=2048%2C1066&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/10/block-gap-post-template.jpg?ssl=1)Because of the way the layout system works in WordPress, it will output CSS that is specific to individual containers to handle the gap between blocks nested within those containers. For the screenshot example, here’s what that CSS looks like: ```css .wp-container-17.wp-container-17 > :first-child:first-child { margin-block-start: 0; } .wp-container-17.wp-container-17 > * { margin-block-start: var(--wp--preset--spacing--plus-4); margin-block-end: 0; } ``` Of course, the ID (`17`) and value will be different on a case-by-case basis. ### Enabling margin and padding The margin and padding settings are a little more straightforward. They are both disabled by default, and you can enable them by setting their values to `true` in `theme.json`: ```json { "version": 2, "settings": { "spacing": { "margin": true, "padding": true } } } ``` This will make the **Margin** and **Padding** controls appear for supported blocks in their inspector controls in the sidebar: [![WordPress editor with a Query Loop block. In the sidebar, the Margin dropdown is shown.](https://i0.wp.com/developer.wordpress.org/files/2023/10/margin-padding-controls.jpg?resize=2048%2C1066&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/10/margin-padding-controls.jpg?ssl=1)Of course, you are free to leave both of these to the default value of `false` or configure them to your liking. ### Disabling user-defined spacing sizes When any one of the `blockGap`, `margin`, or `padding` spacing settings are enabled, WordPress will output a user interface for setting those values for blocks that support them. By default, users can select from a list of preset spacing sizes (see “Spacing scale and sizes” below) or input a custom value. In this screenshot, you can see that there is a custom **Block Spacing** setting chosen for the Buttons block: [![Three buttons in the post editor. In the sidebar, the Block Spacing option is shown.](https://i0.wp.com/developer.wordpress.org/files/2023/10/custom-spacing-size-buttons.jpg?resize=2048%2C1066&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/10/custom-spacing-size-buttons.jpg?ssl=1)You may want to limit users to your predefined spacing scale or sizes for your theme. This is often a good idea if you want to ensure consistent spacing throughout your design. To do this, you must set the `customSpacingSizes` setting to `false`. This disables the custom spacing option in the editor UI but leaves the control for the theme’s defined sizes available: ```json { "version": 2, "settings": { "spacing": { "customSpacingSize": false } } } ``` With custom spacing sizes disabled, the **Block Spacing** option from the Buttons block example will be limited to the theme’s preset sizes: [![Three buttons in the post editor. In the sidebar, the Block Spacing dropdown is shown.](https://i0.wp.com/developer.wordpress.org/files/2023/10/preset-spacing-buttons.jpg?resize=2048%2C1066&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/10/preset-spacing-buttons.jpg?ssl=1)## Defining allowed spacing units If you choose to enable the `settings.spacing.customSpaceSize` option covered in the previous section, you will need to make another choice: which CSS unit values will your theme allow? By default, WordPress lets users select from a subset of possible CSS units (there are dozens in the CSS specification). To choose which units you want to support, you must add them into the `settings.spacing.units` array in `theme.json` (shown with the defaults): ```json { "version": 2, "settings": { "spacing": { "units": [ "px", "em", "rem", "vh", "vw", "%" ] } } } ``` The currently-allowed possible units that you can choose from are: - `px` - `%` - `em` - `rem` - `vw` - `vh` - `vmin` - `vmax` - `ch` - `ex` - `cm` - `mm` - `in` - `pc` - `pt` As of WordPress 6.3, the allowed units are limited to the above list. There is an [open ticket](https://github.com/WordPress/gutenberg/issues/52441) to expand these to support more modern units. ## Spacing scale and sizes One of the most important things that you should configure in your `theme.json` file is your spacing presets. WordPress will generate these presets as CSS custom properties, loading them in the editor and front end. Most designers will use some type of standard scaling system for handling spacing, and WordPress gives you the flexibility to use whatever system you choose. There are two methods for registering your spacing presets: - **`spacingScale`:** A generated scale based on your configuration values. - **`spacingSizes`:** Completely custom-defined spacing sizes. Technically, you can use both of these methods, mixing and matching them. But it is generally recommended to choose one over the other for simplicity. Spacing presets appear as choices for the **Block Spacing**, **Margin**, and **Padding** block controls (for blocks that support them). This means that you can present users with spacing options that are specific to your theme. You can also use these presets in the [Styles](https://developer.wordpress.org/themes/global-settings-and-styles/styles) section in your `theme.json` or custom CSS. WordPress generates a default spacing scale, as shown in this table: | CSS Custom Property | CSS Value | Label | |---|---|---| | `--wp-preset--spacing--20` | `0.44rem` | 2X-Small | | `--wp-preset--spacing--30` | `0.67rem` | X-Small | | `--wp-preset--spacing--40` | `1rem` | Small | | `--wp-preset--spacing--50` | `1.5rem` | Medium | | `--wp-preset--spacing--60` | `2.25rem` | Large | | `--wp-preset--spacing--70` | `3.38rem` | X-Large | | `--wp-preset--spacing--80` | `5.06rem` | 2X-Large | It is unlikely that this scale matches your design. So you will want to choose a method for overriding these default values. ### Custom spacing scale WordPress allows theme authors to create a custom spacing scale by providing a set of configuration instructions. Each step in the scale generates a custom CSS property with the slug of `--wp--preset--spacing--{step}` (steps appear in increments of 10, regardless of their value). The `spacingScale` object has five sub-settings that themes can configure: - **`operator`:** The operator used to increment the scale. The available options are `+` (addition) and `*` (multiplication). The default value is `*`. - **`increment`:** A number in which to increment the scale by when used in conjunction with the `operator` setting. The default value is `1.5`. - **`steps`:** The total number of steps in the scale. The default value is `7`. - **`mediumStep`:** The medium value of the scale. The default value is `1.5`. - **`unit`:** A valid CSS spacing unit. The available options are `px`, `em`, `rem`, `vh`, `vw`, and `%`. The default value is `rem`. The following example is a custom scale with seven steps that increments by `0.25rem`: ```json { "version": 2, "settings": { "spacing": { "spacingScale": { "operator": "+", "increment": 0.25, "steps": 7, "mediumStep": 1, "unit": "rem" } } } } ``` As shown in the screenshot, you should see a range slider the **Padding**, **Margin**, and **Block Spacing** controls for setting your registered values: [![Stack block in the WordPress post editor. In the sidebar, various spacing options are adjusted.](https://i0.wp.com/developer.wordpress.org/files/2023/10/spacing-scale.jpg?resize=2048%2C1066&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/10/spacing-scale.jpg?ssl=1) When there are seven or fewer spacing presets, the interface will show a range slider for spacing controls. But more than seven displays a dropdown select. This applies to both the `spacingScale` method used here and the `spacingSizes` method in the next section. This table represents your custom spacing scale (compare to the default scale to see how things have changed): | CSS Custom Property | CSS Value | Label | |---|---|---| | `--wp-preset--spacing--20` | `0.25rem` | 2X-Small | | `--wp-preset--spacing--30` | `0.5rem` | X-Small | | `--wp-preset--spacing--40` | `0.75rem` | Small | | `--wp-preset--spacing--50` | `1rem` | Medium | | `--wp-preset--spacing--60` | `1.25rem` | Large | | `--wp-preset--spacing--70` | `1.5rem` | X-Large | | `--wp-preset--spacing--80` | `1.75rem` | 2X-Large | The `mediumStep` value is always assigned to the `--wp--preset--spacing--50` preset when WordPress generates the CSS, and the other preset slugs in the scale extend up/down from this middle number in increments of 10. The spacing scale will never go below `--wp--preset--spacing--10`. For scales with more than 10 steps, the bottom end of the scale will not generate presets because the `mediumStep` is always set to `--wp--preset--spacing--50`. #### Disable the spacing scale If you want to disable WordPress’ spacing scale altogether, you can set `steps` to `0` in `theme.json`: ```json { "version": 2, "settings": { "spacing": { "spacingScale": { "steps": 0 } } } } ``` This can be useful when choosing to register completely custom spacing sizes, as covered in the next section. ### Custom spacing sizes If you want more precise control over the spacing options, you can build out the individual spacing sizes instead of using the WordPress spacing scale system. This provides control over each option’s name, size, and slug. The `spacingSizes` property lets you define an array of size objects. Each size object accepts three values: - **`name`:** The human-readable title for the size, which can be translated. - **`size`:** A valid CSS size. This can be a number and unit, a fluid size using `clamp()`, or a reference to another custom CSS property. - **`slug `:** The slug for the size, which will be appended to a generated CSS custom property: `--wp--preset--spacing--{slug}`. The following is an example of creating a five-step scale that increments by `0.25rem`: ```json { "version": 2, "settings": { "spacing": { "spacingSizes": [ { "name": "Step 1", "size": "0.25rem", "slug": "10" }, { "name": "Step 2", "size": "0.5rem", "slug": "20" }, { "name": "Step 3", "size": "0.75rem", "slug": "30" }, { "name": "Step 4", "size": "1rem", "slug": "40" }, { "name": "Step 5", "size": "1.25rem", "slug": "50" } ] } } } ``` You should see a range slider the **Padding**, **Margin**, and **Block Spacing** controls for setting your registered values, as shown here: [![Stack block in the WordPress post editor. In the sidebar, various spacing options are adjusted.](https://i0.wp.com/developer.wordpress.org/files/2023/10/spacing-sizes.jpg?resize=2048%2C1066&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/10/spacing-sizes.jpg?ssl=1)This table represents your custom spacing sizes: | CSS Custom Property | CSS Value | Label | |---|---|---| | `--wp-preset--spacing--10` | `0.25rem` | Step 1 | | `--wp-preset--spacing--20` | `0.5rem` | Step 2 | | `--wp-preset--spacing--30` | `0.75rem` | Step 3 | | `--wp-preset--spacing--40` | `1rem` | Step 4 | | `--wp-preset--spacing--50` | `1.25rem` | Step 5 | #### Creating fluid sizes If you want to use fluid spacing, you must use the `settings.spacing.spacingSizes` method for controlling the size presets. To use fluid sizes, you merely need to add them as the `size` parameter for each of the size objects under `settings.spacing.spacingSizes`. `clamp()`, `min()`, `max()`, and other valid CSS values are supported. Here is an example of a seven-step fluid spacing scale registered as individual sizes in `theme.json`: ```json { "version": 2, "settings": { "spacing": { "spacingSizes": [ { "name": "Fluid Scale -3", "size": "clamp( 0.31rem, 0.11vw + 0.28rem, 0.35rem )", "slug": "minus-3" }, { "name": "Fluid Scale -2", "size": "clamp( 0.47rem, 0.16vw + 0.42rem, 0.53rem )", "slug": "minus-2" }, { "name": "Fluid Scale -1", "size": "clamp( 0.71rem, 0.25vw + 0.63rem, 0.79rem )", "slug": "minus-1" }, { "name": "Fluid Scale +/- 0 (Base)", "size": "clamp( 1.06rem, 0.37vw + 0.95rem, 1.19rem )", "slug": "base" }, { "name": "Fluid Scale +1", "size": "clamp( 1.20rem, 0.85vw + 0.94rem, 1.48rem )", "slug": "plus-1" }, { "name": "Fluid Scale +2", "size": "clamp( 1.34rem, 1.5vw + 0.89rem, 1.86rem )", "slug": "plus-2" }, { "name": "Fluid Scale +3", "size": "clamp( 1.86rem, 3.7vw + -0.05rem, 2.32rem )", "slug": "plus-3" } ] } } } ``` This results in the following values, as shown in this table: | CSS Custom Property | CSS Value | Label | |---|---|---| | `--wp-preset--spacing--minus-1` | `clamp( 0.31rem, 0.11vw + 0.28rem,  0.35rem )` | Fluid Scale -3 | | `--wp-preset--spacing--minus-2` | `clamp( 0.47rem, 0.16vw + 0.42rem,  0.53rem )` | Fluid Scale -2 | | `--wp-preset--spacing--minus-3` | `clamp( 0.71rem, 0.25vw + 0.63rem,  0.79rem )` | Fluid Scale -1 | | `--wp-preset--spacing--base` | `clamp( 1.06rem, 0.37vw + 0.95rem,  1.19rem )` | Fluid Scale +/- 0 (Base) | | `--wp-preset--spacing--plus-1` | `clamp( 1.20rem, 0.85vw + 0.94rem,  1.48rem )` | Fluid Scale +1 | | `--wp-preset--spacing--plus-2` | `clamp( 1.34rem, 1.5vw + 0.89rem,  1.86rem )` | Fluid Scale +2 | | `--wp-preset--spacing--plus-3` | `clamp( 1.86rem, 3.7vw + -0.05rem,  2.32rem )` | Fluid Scale +3 | --- # Typography Source: https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/ Typography is a wide-ranging subject in web design, and no single piece of documentation could do it justice. There are book-length works that dive into the finer details and articles aplenty across the web that teach best practices, tips, and tricks at length. This guide will specifically get you up to speed with the available settings available via `settings.typography` in `theme.json`. Typography is also tightly related to spacing in your theme, so you will need to familiarize yourself with the [spacing settings](https://developer.wordpress.org/themes/global-settings-and-styles/settings/spacing) to get the most out of both guides. You will also take what you learn from this documentation and apply it to your [`theme.json` styles](https://developer.wordpress.org/themes/global-settings-and-styles/styles). ## Enabling and disabling typography options There are several settings that are merely for enabling or disabling elements in the user interface. Each of these properties accept a boolean value, meaning that you can set them to either `true` or `false`. Not every block will support every typography setting. Some are specific to a single block. For example, the `dropCap` property only works for Paragraph blocks. Others are widely used by almost any block with text, such as `customFontSize`. These `settings.typography` properties let you enable or disable features in the interface: - **`customFontSize`:** Whether to let users input custom font sizes. Defaults to `true`. - **`dropCap`:** Whether users can enable a drop-cap for the first letter of the Paragraph block. Defaults to `true`. - **`fontStyle`:** Whether users can select a custom font style. Defaults to `true`. - **`fontWeight:`** Whether users can select a custom font weight. Weight ranges map to the standard **Thin** through **Black** font weights. Defaults to `true`. - **`letterSpacing`:** Whether users can input a custom letter spacing value. Defaults to `false`. - **`lineHeight`:** Whether users can input a custom line height for text. There is no way to register line-height presets, so this option enables a completely custom input. Defaults to `false`. - **`textColumns`:** Whether to show a columns option for the block’s text. Defaults to `false`. - **`textDecoration`:** Whether the user can set the text decoration for a block’s text. The available options are **None**, **Underline**, and **Strikethrough**. Defaults to `true`. - **`textTransform`:** Whether the user can change the letter case for a block’s text. The available options are **None**, **Uppercase**, **Lowercase**, and **Capitalize**. Defaults to `true`. - **`writingMode`:** Whether to enable the text **Orientation** in the interface, allowing users to choose between **Horizontal** and **Vertical** text. Defaults to `false`. Here is what these typography settings look like in the default WordPress `theme.json`: ```json { "version": 2, "settings": { "typography": { "customFontSize": true, "dropCap": true, "fontStyle": true, "fontWeight": true, "letterSpacing": true, "lineHeight": false, "textColumns": false, "textDecoration": true, "textTransform": true, "writingMode": false } } } ``` In this screenshot, take note of the **Typography** panel for the Paragraph block, which has every setting enabled: [![WordPress post editor with a Heading and multiple Paragraph blocks inserted. In the right sidebar, nearly every typography option is shown.](https://i0.wp.com/developer.wordpress.org/files/2023/10/typography-panel.jpg?resize=2048%2C1066&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/10/typography-panel.jpg?ssl=1)Depending on your theme’s audience, you will want to enable only the features that its users will need. For example, you may have a client who only needs to configure the font size. It wouldn’t make sense to show them every setting if it gets in the way of their workflow. A note on drop caps: the current implementation feature is notoriously buggy with different font families, font sizes, and line heights. If you leave this feature enabled, be sure that you test that drop caps look good within your theme’s design. You may need to add custom CSS so that it matches your theme. ## Custom font families WordPress lets you register as many font families as you want via the `settings.typography.fontFamilies` property in `theme.json`. You can add support for both system fonts (those that live on the visitor’s computer) or web fonts (custom fonts bundled with your theme). You’ll learn how to register both of these in this section. These appear as options under the **Typography > Font** field in the inspector panel for blocks that support selecting a font: [![WordPress post editor with a Cover block with inner blocks nested. In the sidebar, the Font dropdown is shown.](https://i0.wp.com/developer.wordpress.org/files/2023/10/font-family.jpg?resize=2048%2C1064&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/10/font-family.jpg?ssl=1)The `settings.typography.fontFamilies` property is an empty array by default. You can register fonts by passing in font family objects with these properties: - **`name`:** *(Required)* The human-readable title for the font family, which can be translated. - **`slug`:** *(Required)* The slug for the size, which will be appended to a generated CSS custom property: `--wp--preset--font-family--{slug}`. - **`fontFamily`:** *(Required)* A valid value that will map to the CSS `font-family` value. Generally, this will be a font stack (a list of families that the browser will try to use in order). - **`fontFace`:** *(Optional)* An array of font faces that are mapped to the `@font-face` CSS at-rule. You only need to use this when bundling custom web fonts with your theme. Here is what the font family setting looks like in the default WordPress `theme.json`: ```json { "version": 2, "settings": { "typography": { "fontFamilies": [] } } } ``` In the following subsections, you will first learn how to register system fonts. Then, you will take the next step and register a custom web font. ### Registering system fonts System fonts are more straightforward than web fonts. You only need to know which fonts you want to use. For this exercise, let’s assume that you want to register two fonts that you will use in your theme: - **Primary:** a transitional serif font stack that will look good across modern devices. - **Secondary:** the user’s system UI font. Add this code to your `theme.json` to register each of the fonts: ```json { "$schema": "https://schemas.wp.org/trunk/theme.json", "version": 2, "settings": { "typography": { "fontFamilies": [ { "name": "Primary", "slug": "primary", "fontFamily": "Charter, 'Bitstream Charter', 'Sitka Text', Cambria, serif" }, { "name": "Secondary", "slug": "secondary", "fontFamily": "system-ui, sans-serif" } ] } } } ``` These options will now appear in the **Typography > Font** dropdown for any blocks that support the feature. WordPress will also generate two CSS custom properties with the `--wp--preset--font-family--{$slug}` format in both the editor and on the front end: ```css body { --wp--preset--font-family--primary: Charter, 'Bitstream Charter', 'Sitka Text', Cambria, serif; --wp--preset--font-family--secondary: system-ui, sans-serif; } ``` You can reference these as `var:preset|font-family|$slug` when you begin using them as [Styles in `theme.json`](https://developer.wordpress.org/themes/global-settings-and-styles/styles/). You can also reference them using `var( --wp--preset--font-family--{$slug} )` directly in CSS. It is generally recommended to use a semantic naming scheme for your font family slugs so that they are more future proof when switching between child themes, style variations, and even from theme to theme. These examples use `primary` and `secondary` since those are widely used terms. It’s best to avoid naming your slugs so that they match the current font family. ### Registering web fonts (font faces) Registering custom web fonts works in much the same way as system fonts. The big difference is that you need to add the `fontFace` property to your font family objects. `fontFace` must be an array of font face objects. Each object accepts these properties that map to descriptors for the [`@font-face` CSS at-rule](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face): - **`fontFamily`:** A valid CSS `font-family` descriptor. - **`fontWeight`:** A range of CSS `font-weight` values. - **`fontStyle`:** A valid CSS `font-style` value. - **`fontStretch`:** A valid CSS font stretch value. - **`src`:** An array of font file URLs where the font files are located (this can be used to support multiple formats, but only one is required). The `src` property is unique in that it allows you to reference a URL that is relative to the `theme.json` file in your theme. Use the `"file:./path/to/file.ext"` format to reference a font bundled with your theme. Let’s try an example. Building off the code from the previous section, suppose you wanted to replace the system UI font with the Open Sans web font. This example will also assume you have downloaded and converted the Open Sans font to the modern `.woff2` format, which is widely supported by most browsers. You’ve also placed these files in your theme’s `/assets/fonts` folder like this: - `/assets` - `/fonts` - `/open-sans.woff2` - `/open-sans-italic.woff2` With your web fonts bundled in your theme and ready to go, add this code to your `theme.json` file to register them: ```json { "$schema": "https://schemas.wp.org/trunk/theme.json", "version": 2, "settings": { "typography": { "fontFamilies": [ { "name": "Primary", "slug": "primary", "fontFamily": "Charter, 'Bitstream Charter', 'Sitka Text', Cambria, serif" }, { "name": "Secondary", "slug": "secondary", "fontFamily": "'Open Sans', sans-serif", "fontFace": [ { "fontFamily": "Open Sans", "fontWeight": "300 800", "fontStyle": "normal", "fontStretch": "normal", "src": [ "file:./assets/fonts/open-sans.woff2" ] }, { "fontFamily": "Open Sans", "fontWeight": "300 800", "fontStyle": "italic", "fontStretch": "normal", "src": [ "file:./assets/fonts/open-sans-italic.woff2" ] } ] } ] } } } ``` Like with system fonts, WordPress will generate CSS custom properties for web fonts. Here is what the CSS output looks like: ```css body { --wp--preset--font-family--primary: Charter, 'Bitstream Charter', 'Sitka Text', Cambria, serif; --wp--preset--font-family--secondary: 'Open Sans', sans-serif; } ``` ## Custom font sizes WordPress lets you register any number of preset font sizes that your theme users can choose from. By registering custom sizes, you can more easily maintain consistent typography across the theme. Custom font sizes appear as options in the **Typography > Size** panel in the inspector controls for blocks that support the feature: [![WordPress post editor showing multiple paragraphs with different font sizes.](https://i0.wp.com/developer.wordpress.org/files/2023/10/font-sizes.jpg?resize=2048%2C1056&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/10/font-sizes.jpg?ssl=1)Note that if you have more than five custom sizes, the UI will show a dropdown select instead of the button group shown in the above screenshot. There are two `theme.json.settings.typography` sub-properties related font sizes: - **`fluid`:** Whether to enable fluid font sizes that scale up on large screens and down on smaller screens. This can be overridden for individual custom sizes. Defaults to `false`. - **`fontSizes`:** An array of font size objects that you can use to customize the available presets that users can choose from. WordPress registers the default sizes of `small`, `medium`, `large`, and `x-large`. Here is what these properties look like in the default WordPress `theme.json`: ```json { "version": 2, "settings": { "typography": { "fluid": false, "fontSizes": [ { "name": "Small", "slug": "small", "size": "13px" }, { "name": "Medium", "slug": "medium", "size": "20px" }, { "name": "Large", "slug": "large", "size": "36px" }, { "name": "Extra Large", "slug": "x-large", "size": "42px" } ] } } } ``` As you can see, WordPress disables fluid font sizes by default and registers four static sizes of its own. In almost all cases, you will want to overwrite these with sizes that match your theme’s design. Like other presets that you can set in `theme.json`, WordPress automatically generates CSS custom properties for font sizes using the `--wp--preset--font-size--{$slug}` format. For the default sizes, this CSS is output in the editor and on the front end: ```css body { --wp--preset--font-size--small: 13px; --wp--preset--font-size--medium: 20px; --wp--preset--font-size--large: 36px; --wp--preset--font-size--x-large: 42px; } ``` WordPress also generates custom CSS classes for each font size preset using the `.has-{$slug}-font-size` naming scheme. The default sizes produce these classes: ```css .has-small-font-size{ font-size: var(--wp--preset--font-size--small) !important; } .has-medium-font-size{ font-size: var(--wp--preset--font-size--medium) !important; } .has-large-font-size{ font-size: var(--wp--preset--font-size--large) !important; } .has-x-large-font-size{ font-size: var(--wp--preset--font-size--x-large) !important; } ``` ### Enabling fluid typography In modern web design, you will almost always utilize fluid typography. This allows your font sizes to scale up or down with the viewport or container. WordPress uses a viewport-based system for fluid typography. But you don’t have to rely on this if you prefer to use something different, such as a container-based system, and can leave it disabled. Suppose you wanted to use the default core sizes but wanted them all to be fluid instead of static values. You can enable this by setting `settings.typography.fluid` to `true` in your `theme.json` file: ```json { "version": 2, "settings": { "typography": { "fluid": true } } } ``` WordPress will now generate fluid sizes for registered font sizes: ```css body { --wp--preset--font-size--small: 13px; --wp--preset--font-size--medium: clamp(14px, 0.875rem + ((1vw - 3.2px) * 0.852), 20px); --wp--preset--font-size--large: clamp(22.041px, 1.378rem + ((1vw - 3.2px) * 1.983), 36px); --wp--preset--font-size--x-large: clamp(25.014px, 1.563rem + ((1vw - 3.2px) * 2.413), 42px); } ``` `14px` is the default minimum font-size limit. Because the `small` size is below that limit, it remained at its static size of `13px`. ### Registering custom font size presets You will undoubtedly want to register font sizes that match your theme’s design instead of sticking with the defaults. To do this, you must pass an array of font size objects to the `settings.typography.fontSizes` property in `theme.json`. Each of these objects accepts several properties: - **`name`:** The human-readable title for the size, which can be translated. - **`size`:** A valid CSS size. This can be a number and unit, a custom fluid size using `clamp()`, or a reference to another custom CSS property. - **`slug`:** The slug for the size, which will be appended to a generated CSS custom property: `--wp--preset--spacing--{slug}`. - **`fluid`:** A boolean value to enable or disable fluid typography for this specific size, overwriting the global property. Alternatively, it can be an object containing: - **`min`:** The minimum value that the font size can scale down to. Must be a valid CSS size. - **`max`:** The maximum value that the font size can scale up to. Must be a valid CSS size. Let’s register a simple set of custom sizes with static values first. Add this code to your `theme.json` file: ```json { "$schema": "https://schemas.wp.org/trunk/theme.json", "version": 2, "settings": { "typography": { "fontSizes": [ { "name": "Small", "size": "1rem", "slug": "sm" }, { "name": "Medium", "size": "1.25rem", "slug": "md" }, { "name": "Large", "size": "1.5rem", "slug": "lg" } ] } } } ``` Just like with the default size presets, WordPress will automatically generate the CSS for each in both the editor and on the front end: ```css body { --wp--preset--font-size--sm: 1rem; --wp--preset--font-size--md: 1.25rem; --wp--preset--font-size--lg: 1.5rem; } ``` Now, let’s take this one step further. In the previous example, you registered Small, Medium, and Large sizes. Suppose that you wanted the Small size to maintain its value regardless of the browser’s viewport width. But you want the Medium and Large size to scale along with the viewport. Using the `fluid` property, let’s configure these on a size-by-size basis. Add this code to your `theme.json`: ```json { "$schema": "https://schemas.wp.org/trunk/theme.json", "version": 2, "settings": { "typography": { "fluid": true, "fontSizes": [ { "name": "Small", "size": "1rem", "slug": "sm", "fluid": false }, { "name": "Medium", "size": "1.25rem", "slug": "md", "fluid": { "min": "1rem", "max": "1.5rem" } }, { "name": "Large", "size": "1.5rem", "slug": "lg", "fluid": { "min": "1.25rem", "max": "2rem" } } ] } } } ``` WordPress will generate these CSS custom properties: ```css body { --wp--preset--font-size--sm: 1rem; --wp--preset--font-size--md: clamp(1rem, 1rem + ((1vw - 0.2rem) * 1.136), 1.5rem); --wp--preset--font-size--lg: clamp(1.25rem, 1.25rem + ((1vw - 0.2rem) * 1.705), 2rem); } ``` There aren’t many limits to how you can customize this for your theme. The above offers an intro to registering custom font sizes, but you have full control over how this works for your theme. For a deeper understanding of fluid font sizes, read [Intrinsic design, theming, and rethinking how to design with WordPress](https://developer.wordpress.org/news/2023/02/intrinsic-design-theming-and-rethinking-how-to-design-with-wordpress/) on the Developer Blog. --- # Use Root Padding Aware Alignments Source: https://developer.wordpress.org/themes/global-settings-and-styles/settings/use-root-padding-aware-alignments/ The `settings.useRootPaddingAwareAlignments` property can be one of the most confusing settings in `theme.json`. It is not tied to an interface option. Nor is it used for registering presets. Instead, it’s for configuring where WordPress places your theme’s horizontal padding styles. This means it works in conjunction with `styles.spacing.padding` in `theme.json`. You can find out more about general styling in the [Styles documentation](https://developer.wordpress.org/themes/global-settings-and-styles/styles), but you’ll learn how this specific style works alongside this setting here. ## What is root padding? Before understanding how the `settings.useRootPaddingAwareAlignments` property works, you must first understand what root padding is. Root padding is the padding that is applied to a web page’s “root” element. In the case of WordPress themes, this is the `` element. To customize the spacing for the root element, you must target the `styles.spacing.padding` element in `theme.json`. Take the following `theme.json` snippet, for example. It adds `0` for top and bottom padding and `2rem` for left and right padding: ```json { "version": 2, "styles": { "spacing": { "padding": { "top": "0", "bottom": "0", "left": "2rem", "right": "2rem" } } } } ``` By default, this will add `2rem` of padding on the left and right sides of the `` (root) element. As shown in this screenshot, there is horizontal padding at the root, and a full-width Cover block stretches until it hits that padding: [![WordPress site header with a Cover block background. It has padding to the left and right of it so that it doesn't stretch the full width of the screen.](https://i0.wp.com/developer.wordpress.org/files/2023/10/root-padding.jpg?resize=2048%2C1024&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/10/root-padding.jpg?ssl=1)This is the CSS that WordPress outputs based on the above `theme.json` code: ```css body { padding-top: 0; padding-right: 2rem; padding-bottom: 0; padding-left: 2rem; } ``` But—and this is where things can look odd to seasoned designers—when `settings.useRootPaddingAwareAlignments` is enabled, the “root” padding is no longer applied to the root element. It is applied to container blocks like Group. You’ll learn more about why this happens in the next section. The main goal right now is to understand that root padding is traditionally applied to the `` element, and that is what most theme authors would expect. For root padding aware alignments, WordPress is only concerned with the horizontal (left and right) padding. So the vertical (top and bottom) padding is not relevant to this documentation. ## Enabling root padding aware alignments By default, WordPress will apply root padding to the `` element. If this makes sense for your theme’s design, you don’t need to do anything else. *But what if you want to let full-width items stretch to the edges of the screen* ***and*** *have padding on the root element?* When compared to the first screenshot, notice how the Cover block stretches to edges of the screen but there is padding still applied to the nested blocks here: [![WordPress site header with a Cover block background that stretches the full width of the screen.](https://i0.wp.com/developer.wordpress.org/files/2023/10/root-padding-aware.jpg?resize=1024%2C510&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/10/root-padding-aware.jpg?ssl=1)This is a common design pattern, and there are several ways to stretch elements beyond their containers in CSS. But WordPress has a standard approach that would work with any theme. That’s where `settings.useRootPaddingAwareAlignments` comes in. When this property is set to `true`, it puts the root padding on container elements instead of ``. This must also be combined with a `styles.spacing.padding` object, particularly with horizontal padding applied. Try this code in your `theme.json`: ```json { "version": 2, "settings": { "useRootPaddingAwareAlignments": true }, "styles": { "spacing": { "padding": { "top": "0", "bottom": "0", "left": "2rem", "right": "2rem" } } } } ``` There is no right or wrong way to handle root padding. It is a situational setting where you must decide which option is best for your theme’s design. ### How does this work? It’s not particularly vital to know how WordPress handles all of this under the hood, but sometimes you might just want a deeper understanding of what’s going on. When you enable `settings.useRootPaddingAwareAlignments`, as shown in the last `theme.json` example, WordPress will generate two new bits of CSS. The first is that it defines some CSS custom properties for the root padding: ```css body { --wp--style--root--padding-top: 0; --wp--style--root--padding-right: 2rem; --wp--style--root--padding-bottom: 0; --wp--style--root--padding-left: 2rem; } ``` The second is that it adds a `.has-global-padding` class: ```css .has-global-padding { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); } ``` This class is then given to container blocks with constrained layouts (for example, Group blocks with the **Layout > Inner blocks use content width** option enabled): ```markup
    ``` Beyond that, WordPress adds inline CSS to stretch nested wide and full-width blocks beyond their parent block’s width (including the additional padding that’s added to the width). --- # Blocks Source: https://developer.wordpress.org/themes/global-settings-and-styles/settings/blocks/ Most settings in `theme.json` let you configure properties at the global level. This means that they apply to all blocks that support them. But WordPress also lets you control this at the block level. That’s what the `settings.block` property is for—you can configure everything from typography, to colors, to spacing, and more for individual blocks. Before moving forward with this page of the handbook, it is important to familiarize yourself with at least some of the existing [`theme.json` settings](https://developer.wordpress.org/themes/global-settings-and-styles/settings/). This way, you can apply them on a per-block basis. ## How block settings work In the previous pages of the `theme.json` settings documentation, you learned how to configure specific properties at the global level. Essentially, this means that they are applied to all blocks that support the specific property/feature. You would have configured many of these properties in your `theme.json` (shortened for example—you can review all available properties via the main [settings documentation](https://developer.wordpress.org/themes/global-settings-and-styles/settings/)): ```json { "version": 2, "settings": { "border": {}, "color": {}, "custom": {}, "spacing": {}, "typography": {} } } ``` But there are times when you need to add settings at the individual block level, and anything set for the block will overrule its global setting. So let’s explore an example that shows block-specific settings overwriting the global settings. For this example, you will create a custom color palette, which you can learn about in the [color settings documentation](https://developer.wordpress.org/themes/global-settings-and-styles/settings/color). This will be applied globally and used for every block’s color picker. Then, you will create a custom color palette for the Cover block that’s only shown for the Cover block. First, add your global color palette in `theme.json` with two colors named `base` and `contrast`: ```json { "version": 2, "settings": { "color": { "palette": [ { "color": "#0284c7", "name": "Base", "slug": "base" }, { "color": "#ffffff", "name": "Contrast", "slug": "contrast" } ] } } } ``` Now add a Cover block and some nested text in the WordPress editor, saving the **Text** and **Overlay** colors for the block to your two custom colors: [![WordPress post editor showing a Cover block with a blue background and white text.](https://i0.wp.com/developer.wordpress.org/files/2023/10/cover-global-colors.jpg?resize=2048%2C1071&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/10/cover-global-colors.jpg?ssl=1)As you can see, the Cover block currently uses the global color palette that you configured in your `theme.json` file. Suppose that you wanted the Cover block to use an orange color palette. You can configure that by targeting `settings.blocks[core/cover].color.palette` in your `theme.json` file and passing an array of custom colors. Add this new section to your existing `theme.json` so that it looks like this: ```json { "version": 2, "settings": { "color": { "palette": [ { "color": "#0284c7", "name": "Base", "slug": "base" }, { "color": "#ffffff", "name": "Contrast", "slug": "contrast" } ] } "blocks": { "core/cover": { "color": { "palette": [ { "color": "#ea580c", "name": "Base", "slug": "base" }, { "color": "#fff7ed", "name": "Contrast", "slug": "contrast" } ] } } } } } ``` As shown in the `theme.json` example, you use the same organizational structure for block settings as you do for global settings (i.e., `settings.color` at the global level but `settings.blocks[core/cover].color` at the block level). If you refresh your browser window, your Cover block should now show the new colors: [![WordPress post editor showing a Cover block with an orange background and white text.](https://i0.wp.com/developer.wordpress.org/files/2023/10/cover-block-colors.jpg?resize=2048%2C1071&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/10/cover-block-colors.jpg?ssl=1)If you check other blocks, they will still use the global color palette. Only the Cover block will use this custom orange palette. Per-block color palettes are just the tip of the iceberg. You can configure any `theme.json` for any block (assuming the block supports it). This gives you an incredible amount of control over how your theme works. When targeting a block’s settings, you must know both its namespace and slug. Above, you learned that the Cover block has the namespace (`core`) and slug (`cover`), creating the namespace/slug combination of `core/cover`. All core WordPress blocks have the `core` namespace, and you can find this information for any block (including from third-party plugins) in its `block.json` file. ## Default block settings Believe it or not, WordPress actually configures a couple of default block settings in `theme.json`. Generally, this would be left to themes, but these settings are primarily enabled for backward compatibility with features from older versions of WordPress. WordPress enables a few settings for the Button and Pullquote blocks by default. Here is what this looks like in the default `theme.json`: ```json { "version": 2, "settings": { "blocks": { "core/button": { "border": { "radius": true } }, "core/pullquote": { "border": { "color": true, "radius": true, "style": true, "width": true } } } } } ``` You can overwrite these block-specific settings in your `theme.json` file just as you learned to do in the previous section of this documentation. If you are wondering why some of your global settings do not seem to apply to certain blocks, particularly Button and Pullquote, it is likely because they are being set at the block level. You will need to override these in `settings.blocks` in your `theme.json` if you want a different behavior. --- # Settings Reference Source: https://developer.wordpress.org/themes/global-settings-and-styles/settings/settings-reference/ The document is a reference to the available settings properties that you can configure via the `settings` object in `theme.json`. Each of the settings has an in-depth guide on how to use it within the [Settings documentation](https://developer.wordpress.org/themes/global-settings-and-styles/settings/). ## Appearance Tools `settings.appearanceTools` is a top-level property with no sub-properties nested beneath it. It is documented at [Settings: Appearance Tools](https://developer.wordpress.org/global-settings-and-styles/settings/appearance-tools/). | Property | Type | Default | |---|---|---| | `appearanceTools` | boolean | `false` | ## Border `settings.border` is an object that supports the nested properties listed in the below table. It is documented at [Settings: Border](https://developer.wordpress.org/global-settings-and-styles/settings/border/). | Property | Type | Default | |---|---|---| | `color` | boolean | `false` | | `radius` | boolean | `false` | | `style` | boolean | `false` | | `width` | boolean | `false` | Enabling any one of the `color`, `style`, or `width` settings will automatically enable the other two since the properties are linked together. ## Color `settings.color` is an object that supports the nested properties listed in the below table. It is documented at [Settings: Color](https://developer.wordpress.org/global-settings-and-styles/settings/color/). | Property | Type | Default | Props | |---|---|---|---| | `background` | boolean | `true` | — | | `custom` | boolean | `true` | — | | `customDuotone` | boolean | `true` | — | | `customGradient` | boolean | `true` | — | | `defaultDuotone` | boolean | `true` | — | | `defaultGradients` | boolean | `true` | — | | `defaultPalette` | boolean | `true` | — | | `duotone` | array <object> | `array` | `colors`, `name`, `slug` | | `gradients` | array <object> | `array` | `gradient`, `name`, `slug` | | `link` | boolean | `false` | — | | `palette` | array <object> | `array` | `color`, `name`, `slug` | | `text` | boolean | `true` | — | ## Custom `settings.custom` is an object that supports any number of nested custom properties, as shown in the below table. It is documented at [Settings: Custom](https://developer.wordpress.org/global-settings-and-styles/settings/custom/). | Property | Type | Default | |---|---|---| | `custom.` | any | — | ## Dimensions `settings.dimensions` is an object that supports the nested properties listed in the below table. It is documented at [Settings: Dimensions](https://developer.wordpress.org/global-settings-and-styles/settings/dimensions/). | Property | Type | Default | |---|---|---| | `minHeight` | boolean | `false` | ## Layout `settings.layout` is an object that supports the nested properties listed in the below table. It is documented at [Settings: Layout](https://developer.wordpress.org/global-settings-and-styles/settings/layout/). | Property | Type | Default | |---|---|---| | `contentSize` | string | `""` | | `wideSize` | string | `""` | ## Lightbox `settings.lightbox` is an object that supports the nested properties listed in the below table. It is documented at [Settings: Lightbox](https://developer.wordpress.org/global-settings-and-styles/settings/lightbox/). | Property | Type | Default | |---|---|---| | `allowEditing` | boolean | `true` | | `enabled` | boolean | `false` | This setting is only available as of WordPress 6.4 and is specific to the core Image block (`core/image`). ## Position `settings.position` is an object that supports the nested properties listed in the below table. It is documented at [Settings: Position](https://developer.wordpress.org/global-settings-and-styles/settings/position/). | Property | Type | Default | |---|---|---| | `sticky` | boolean | `false` | ## Shadow `settings.shadow` is an object that supports the nested properties listed in the below table. It is documented at [Settings: Shadow](https://developer.wordpress.org/global-settings-and-styles/settings/shadow/). | Property | Type | Default | Props | |---|---|---|---| | `defaultPresets` | boolean | `true` | | | `presets` | array <object> | `array` | `name`, `shadow`, `slug` | ## Spacing `settings.spacing` is an object that supports the nested properties listed in the below table. It is documented at [Settings: Spacing](https://developer.wordpress.org/global-settings-and-styles/settings/spacing/). | Property | Type | Default | Props | |---|---|---|---| | `blockGap` | boolean\|null | `null` | — | | `customSpacingSize` | boolean | `true` | — | | `margin` | boolean | `false` | — | | `padding` | boolean | `false` | — | | `spacingScale` | object | `object` | `operator`, `increment`, `steps`, `mediumStep`, `unit` | | `spacingSizes` | array <object> | `array` | `name`, `size`, `slug` | | `units` | array <string> | `[ "px", "em", "rem", "vh", "vw", "%" ]` | — | ## Typography `settings.typography` is an object that supports the nested properties listed in the below table. It is documented at [Settings: Typography](https://developer.wordpress.org/global-settings-and-styles/settings/typography/). | Property | Type | Default | Props | |---|---|---|---| | `customFontSize` | boolean | `true` | — | | `dropCap` | boolean | `true` | — | | `fontFamilies` | array <object> | `array` | `fontFace`, `fontFamily`, `name`, `slug` | | `fontSizes` | array <object> | `array` | `fluid`, `name`, `size`, `slug` | | `fontStyle` | boolean | `true` | — | | `fontWeight` | boolean | `true` | — | | `fluid` | boolean | `false` | — | | `letterSpacing` | boolean | `true` | — | | `lineHeight` | boolean | `false` | — | | `textColumns` | boolean | `false` | — | | `textDecoration` | boolean | `true` | — | | `textTransform` | boolean | `true` | — | | `writingMode` | boolean | `false` | — | ## Use Root Padding Aware Alignments `settings.useRootPaddingAwareAlignments` is a top-level property with no sub-properties nested beneath it. It is documented at [Settings: Use Root Padding Aware Alignments](https://developer.wordpress.org/global-settings-and-styles/settings/use-root-padding-aware-alignments/). | Property | Type | Default | |---|---|---| | `useRootPaddingAwareAlignments` | boolean | `false` | This setting works together with `styles.spacing.padding` in `theme.json`. If enabled, `styles.spacing.padding` must be an object that defines the `top`, `right`, `bottom`, and `left` styles separately. --- # Applying Styles Source: https://developer.wordpress.org/themes/global-settings-and-styles/styles/applying-styles/ Traditionally, theme authors would style everything from a stylesheet—and they still sometimes must. In modern WordPress, you can also style most, if not all, of your theme directly from your `theme.json` file. When you use this standard system, it is also reflected in the **Appearance > Editor > Styles** interface. This means your theme’s users with access to that admin screen can also make changes that easily work alongside your theme’s styles. But it also means that you can design your theme directly from this visual interface if you choose to do so. `theme.json` supports styles at three different levels: - Root (global) - Elements - Blocks In this document, you will learn the syntax necessary for styling each of these things via JSON. ## Styling the root element When referring to the “root” element in WordPress themes, we’re specifically talking about the HTML `` tag. It’s the root of the visual output for the page. Technically, when styling the root element, you are adding *global* styles that trickle down through the design and are used unless a more specific element or block style overrides them. For example, you’ll likely want to set a default font-family or font-size that is used across the entire design. But you’ll, of course, want to change that in specific instances. Because these are global styles, it means that they belong directly under the `styles` property. So let’s add a default text and background color to show how this works: ```json { "version": 2, "styles": { "color": { "text": "#000000", "background": "#f5f1ea" } } } ``` As you can see, the `color` property is nested directly beneath the `styles` property. This means that the `text` and `background` colors are applied directly to the `` element by WordPress, resulting in this CSS in the editor and on the front end: ```css body { background: #f5f1ea; color: #000000; } ``` And because of the way the *cascade* works in CSS, these colors will be used for everything, unless a more specific style rule overwrites it. If you open your site on the front end or via **Appearance > Editor** in the WordPress admin, you should see your colors applied: [![WordPress Site Editor with Styles interface open, showing the theme's colors.](https://i0.wp.com/developer.wordpress.org/files/2023/10/styles-root-colors.jpg?resize=2048%2C1071&ssl=1)](https://i0.wp.com/developer.wordpress.org/files/2023/10/styles-root-colors.jpg?ssl=1)You are not just limited to colors. You can add `typography`, `spacing`, and more here. The root element supports almost all of the available style properties, which you can reference in the [Supported Styles](https://developer.wordpress.org/themes/global-settings-and-styles/styles/styles-reference/) documentation. The `styles.spacing.padding` property has a unique use case when used in conjunction with `settings.useRootPaddingAwareAlignments`. For more information on how these two work together, read the [Use Root Padding Aware Alignments](https://developer.wordpress.org/themes/global-settings-and-styles/use-root-padding-aware-alignments/) documentation. ## Styling elements WordPress has a standard system for styling elements via `theme.json`. In this case, “elements” usually maps to actual HTML elements. But there are cases where it’s referring to something that doesn’t map directly to a single HTML element. In general, these should be reasonably straightforward. Just like styling the root element and blocks, which you’ll learn about below, you can apply a wide range of the [supported styles](https://developer.wordpress.org/themes/global-settings-and-styles/styles/styles-reference/) to elements. The currently-supported elements are: - **`button`:** Applied to `