Layers Child Theme Author Guide

This guide provides an overview of what the strengths and limitations of child themes are, how to go about building one for Layers, and how to add or remove functionality the right way. The result should be a clean, WordPress-compliant, dream-to-support theme for you or your client!

What is a Child Theme?

A child theme is jut like any other theme except it is able to inherit all of the functionality and front-end structure from Layers (the “parent”) .

There are a few reasons why you would want to use a child theme:

  • If you modify Layers directly, you or your client will not be able to update it without losing the changes
  • Child themes greatly speed up development time.
  • Your child theme is essentially a self-contained set of changes which you are in a better position to track and manage.
  • Your changes may only require 100 lines of code which can be organized in one place, whereas modifying the original disperses your changes throughout 1000 lines of code.
  • Supporting 100 lines is much easier than 1000 – If you modify Layers, it becomes a derivative that you are responsible for supporting and maintaining.
  • Using a child theme is a better way to to learn about WordPress theme development.

When to Use a Child Theme

The division between themes and plugins in WordPress has been a bit blurry for a long time, as both can introduce new functionality to a WordPress install.

You need a Child Theme when:

  • You want to re-style a theme without or beyond what the WordPress customizer controls or other plugins allow you to do,
  • You want to add a bit of code to a specific place (such as a search field in the header) or
  • You want to add custom page templates

When you need to build an Extension (plugin):

  • You want to add Custom Post Types
  • You want to add Layers Builder Widgets

Child themes are for presentation, whereas extensions are for extending functionality.

If you just want to easily package and transfer Layers Page Builder Presets and CSS, you can do that most easily with a Style Kit and do not need a Child Theme. This is the best option for non-developers.

Theme vs Extension vs Style Kit

  • Style Kit: Collection of presets generated from the Layers Customizer. Style Kits include the page builder widget setup, options and color settings, along with any internal assets required such as fonts or icons.
  • Child Theme: Used when a style kit is not enough and usually includes multiple stylesheets, additional scripts and a functions file defining custom actions and filters.
  • Extension: Used to introduce totally new functionality to Layers sites, including custom post types and their page templates.

Author Requirements

This guide uses standard techniques for front-end development that require you to have a basic understanding of CSS and PHP . We reference several WordPress hooks, functions and template tags that can be found on the WordPress Codex, as well as several Layers hooks and functions which are linked directly to our Theme API reference. We recommend the following resources if you are just starting out:

If you have built a WordPress theme before, you may find some of this guide familiar. However, beyond the stylesheet and functions setup, there are several special components and methods for working with the Layers API that are important to learn and comprehend, as the primary difference between a normal WordPress theme and a Layers child theme is that it must be designed to work with the functionality Layers (and by extension, the plugins created for Layers) provide.

Ready to start building your theme? Continue on with the next chapter linked below or Learn How to Setup a Local Development Environment first

Creating a Child Theme from scratch is fairly simple. This section will take you through creating the bare-bones structure for your child theme that you can then fill with all your custom code.

You will need:

  • HTML or Plain-Text editor such as Sublime Text (free)
  • Image editor capable of creating and editing .png files

Create the Folder

  1. Create a folder with a lower-case name. Use hyphens to separate multiple words. In this example, we call our child theme “layers-child”:child-theme-folder
  2. Create a new .css document and save it inside this folder as style.css
  3. Create a new .php document and save it inside this folder as functions.php
  4. Create a new .png image that is 880 pixels wide and 660 pixels tall to setup your theme thumbnail and save it inside this folder as screenshot.png

You now have a very basic skeleton for your theme with the following structure:

Structuring Your Theme

Your child theme only requires one file to work, style.css . However, you will probably end up including additional templates, scripts, stylesheets or images, which requires the functions.php . The file structure of these additional files  should follow the Layers theme structure. Our recommended structure is as follows:

In cases where you plan to add additional files such as images, scripts or template overrides, the structure of your child should match the parent as closely as possible. For a detailed overview of the recommended structure, see Structuring Your Theme.

Of course, if you are starting from scratch, your files don’t contain any code and do nothing useful yet. Let’s fix that by setting up the style.css :

Setup style.css

The style.css must declare the parent template folder name in its header to correctly inherit the parent theme’s functionality and structure. All of your child theme styling belongs in this file.

Below is an example of what this stylesheet header looks like:

Theme Name:  should match the child theme’s folder name and can be capitalized. This value is used to display your theme’s name in WordPress.

Description: to provide a little supporting detail

Author: set here as us – change it to you!

Template:  layerswp  – the folder name of our parent theme, Layers – this must be exact!

Version: Start with 1.0.0 – for more advice on versioning, see Software Versioning, Change Significance on Wikipedia

Finally we have our License and License URI. As a child theme of Layers, this must remain GPL2 with the same URL as shown in our example above.

The color reference is optional, but helps keep your main color selections consistent, especially if you like designing in the browser.

Table of Contents: This keeps your CSS sections organized and easy to scan. It is also a requirement if you intend to submit your theme to ThemeForest. Each item in the table of contents corresponds to a commented heading, for example:

Avoid using @import to load additional css file(s) from a different location (there is no good reason to do that.) Put all CSS in this file.

Setup the functions.php

The functions.php is where the majority of your custom functions and hooks will reside.By default, it looks sad and empty. Not all programs create PHP files correctly, so make sure it begins with the correct PHP tag, like this:

That’s all you need for now – we will return to this file later to add several functions.

Install & Activate

You’re ready to activate your theme! You can either zip the child theme folder and install via the WordPress admin, or drop the folder into wp-content\themes directory on your WordPress install directly or over FTP. When complete, continue with the next section, Styling & Fonts

Note: WordPress considers a child theme to be an entirely separate theme from the parent with regard to theme options and widgets (including Layers page setups). If you had widgets and customizer options setup for Layers, you can reactivate Layers, Backup the Layouts or Widgets and re-import them after reactivating your child theme.

The first thing you’ll probably want to dive into and test out is the restyling aspect of your child theme. This section provides several tips on rapid restyling techniques, choosing selectors, using fonts and images, and troubleshooting override problems that may occur.

Before you begin, ensure you have checked out how to setup your child theme files.

There are two main parts of your child theme’s styling, the stylesheet (or style.css) and the customizer defaults, which are best stored in your functions.php

Color and Font Defaults

A huge part of Layers is allowing users to customize details of their site style such as layouts, typography and colors within the Site Settings and builder widget controls in the Customizer. It is important for your theme to use customizer defaults as a way to override or reset the original Layers or Layers Pro settings  so your child theme loads as intended when activated. Defaults allow your theme to look the way you like, but also allow users to change the fonts or color options and have them work properly. In other words, avoid using CSS to lock users into colors, fonts or other styling that the Customizer options are intended to set. This includes header colors, body fonts etc with overqualified selectors or which us !important. More on this in a minute.

Defaults are set in your child theme functions.php  with a simple filter of the layers_customizer_control_defaults  hook.

In this example, we set the default Header Layout, Heading, Body and Form font, header and footer colors, and default number of footer widget areas to name a few. When someone installs and activates this child theme, these options will be preset in the customizer to aid in helping the user achieve the theme’s demo look as effortlessly as possible.

Let’s break it down:

On line 1, define a unique name for your custom function. Here we simply call it layers_child_customizer_defaults. Yours might be something like “layers_business_customizer_defaults” if your theme is named Layers Business.

On line 3 you can set each Layers customizer control default in the $defaults array.  Each option is added to the array in this way and followed by a comma:

The options are mostly self-explanatory, but you may find a detailed overview of all the options and how to correctly format the value in the  layers_customizer_control_defaults reference.

For options that take a hex color vaue such as site-accent-color, you may set a blank value  so your child theme CSS takes precedent when the option is reset or cleared. Custom colors set by the user will still override your CSS.

Finally on line 17, use add_filter  to hook your $defaults  arguments (layers_child_customizer_defaults) into the original (layers_customizer_control_defaults).

See, not so bad! We will cover hooking and filtering in more detail in the next chapter to help you use custom functions to do things like add custom HTML or widget areas to your theme.

style.css

Now that you have the defaults setup, you can move on to more specific tweaking in the child theme style.css . As you begin to build your child theme stylesheet, you have several options for how to go about overriding original styles. The most efficient and effective method is to use the original selectors and properties used.

Do not copy entire Layers stylesheets into your Child Theme or style.css

Layers divides up its styling into several primary stylesheets to make referencing these easier, which are explained below:

framework.css

Contains all of the structural styling – in most cases you should never change any aspect of framework styles beyond padding, as everything built for layers depends on the grids and rules this stylesheet sets forth.

components.css

Contains the styling for widgets and other Layers components. The Customizer allows control over most of the styling in here, so change with caution.

responsive.css

All responsive styling contains all of the media queries for handling layout changes on smaller screens.

woocommerce.css

Custom styling for Layers that covers WooCommerce shop pages, checkout and cart, mainly to support Layers sidebar settings and framework colors.

These links may be used for reference to quickly view the original style in context of its dependent or parent selectors that may come before and after it, but we recommend using your Browser Inspector.

Rapid Restyling

To begin restyling,  start with your blank style.css , or  work from the sample child theme style.css. Never copy the original stylesheets into your child theme, as this not only makes your child theme immune to parent style fixes or updates, but loads a bunch of unnecessary data.

The best practice is to use the same or a more qualified selector as the parent style to override only the properties you wish to change. To do this quickly, the Browser Inspector and an extension like DevKit are your power tools for building the safest override CSS.

Below are some tips for how we quickly build child theme stylesheets using the Browser Inspector:

  1. Equip yourself with a webkit browser with an Inspector you enjoy working with.
  2. Review the CSS Best Practices for styling Layers Child Themes
  3. Use the WordPress customizer to access the DevKit editing panels and easily copy/paste info from the inspector to DevKit or the CSS panel in the Customizer while viewing the changes in the preview pane.
  4. Work from top-down
  5. Test all changes in live editing mode in the inspector or via DevKit and be sure to test all page templates/layouts.
  6. Copy the dominant selector and the properties you can override into the custom css
  7. If using DevKit, deactivate when you are done and copy the contents of the CSS panels into your child theme style.css.

If you are new to using the Browser Inspector in combination with the WordPress Customizer, take a moment to go through CSS Styling Using the Browser Inspector & Customizer, a primer on rapid restyling – it will make your life easier!

Loading CSS

Layers does not load any styles in its style.css , but instead uses several stylesheets to organize specific parts of the design. The framework.css  is the main stylesheet controlling the overall layout and should always load first, followed by all of its dependents such as components and responsive CSS. Your child theme, if all styling is in the style.css as it should be, also does not need to enqueue or load anything special.

Enqueuing  Stylesheets

Layers will already enqueue the child theme stylesheet and its own stylesheets, so you do not need to use style enqueues unless you have additional stylesheets.

Use enqueueing instead of @import!

You may wish to enqueue the parent style.css  for the purpose of easily determining parent version when viewing the source in the browser.

Here is how you would write a style enqueue function:

On line 5 above we begin with hooking wp_enqueue_scripts  with our custom function layers_child_styles  which can be whatever you want, ie layers_mythemename_styles .  This will take the content of our function and process it when wp_enqueue_scripts runs in WordPress on page load.  The function_exists  condition on line 7 simply checks that this function does not already exist somewhere else, which would cause a conflict.

Within wp_enqueue_style  we have two important things going on in lines 13 and 14. The get_template_directory_uri()  hook returns the correct url to the parent theme‘s folder, and the array allows us to set the ID of another stylesheet we want this one to be dependent on.

  • You do not need to enqueue the child theme style.css. This is already done by Layers.
  • You only need to enqueue the parent style.css if you want to be able to easily reference the Layers version when viewing source on customer sites running your child theme (recommended).

Setting the Right Path

There are several different pathing methods in WordPress that you use depending on if the file is in the parent theme folder, your child theme folder, or a plugin. The following explains the difference between all of these similar, confusing tags:

get_template_directory_uri()

Returns a URL path to the parent theme directory without a trailing slash (eg: . Used most often when enqueuing scripts and styles located in the parent theme directory.

get_stylesheet_directory_uri()

Returns a URL path to the child theme directory without a trailing slash (eg: http://www.yoursite.com/wp-content/themes/layers-child) . Used most often when enqueuing scripts and styles located in the child theme directory.

get_stylesheet_directory()

Returns an absolute server path without a trailing slash (eg: /home/user/public_html/wp-content/themes/layers-child). Used most often in CSS when defining image paths.

get_template_directory()

Returns an absolute server path to the parent theme directory without a trailing slash (eg: /home/user/public_html/wp-content/themes/layers). In most cases, this is never used in your child theme.

plugins_url()

Returns the absolute URL to the plugins directory without a trailing slash.

For a more detailed understanding of enqueues and dependencies, see the following:

Setting Dependents

Overrides in your child stylesheet a bit nightmarish if you are not using the exact selectors to override, or have components or plugins loading in your theme that need separate stylesheet enqueues. Setting dependents on your enqueues is the correct way of dealing with this.

This technique is also helpful in situations where a plugin is loading styles after your child theme styles and you need to override them.

To learn more about CSS specificity, see this wonderful article by Smashing Magazine.

The following example shows how a theme might enqueue a special stylesheet that supports a library being used (such as SimplePie)

Now when the page is rendered, these stylesheets will be loaded AFTER the child theme stylesheet, which will come after Layers by default. To ensure they load only if a specific stylesheet loads, we add a dependency for that style’s ID in the array argument on line 14. The Layers parent style ID is always 'layers-framework' and your child is always 'layers-style'

Image, Font and Icon Replacement

Layers does not use image-based icons or sprites in the front-end theme, so there is no need for replacement, however you may wish to include a different font-icon for use in your own templates and styles. To ensure the fastest load time for your site, font icon libraries should be included in your theme in a sub-directory of the assets folder, for example, but can also be enqueued from a hosted source or using a library already included in WordPress or Layers.

FontAwesome

FontAwesome is now included in the Layers Core and does not need to be included separately. 

If you need to access icon fonts in a beta version of FontAwesome that is newer than the latest Layers verion, you must dequeue the core stylesheet and enqueue yours instead. The dequeue is a safety measure in the event font-awesome is being enqueued from a plugin.

When including an external library in your child theme, you would set the child theme-relative path to the file as normal, or the full url to the hosted file.

Google Fonts

There is no need to add Google fonts or font style enqueues, as Layers already does this. Instead, set the font family in the customizer defaults as described at the beginning of the article. Example with just the font settings:

This method is important, as it saves you a ton of time writing font-replacement CSS while preserving the theme user’s ability to customize their fonts.

Custom Fonts

Custom fonts that are not hosted by a font service may be added to your child theme, along with the appropriate licenses, via @font-face in your style.css, or more efficiently through a standard enqueue.

To enqueue a custom font, create a separate stylesheet to house the @font-face CSS, such as a fonts.css. Then enqueue the stylesheet as a dependent of the parent theme’s typography style to ensure it loads before the child stylesheet:

Fonts should also be enqueued if remotely hosted. The advantage of using a font service is better handling of things like weights, character sets and alternates which, when loaded using @font-face, can reduce performance or encounter rendering bugs.

It is always best to include files in your theme and enqueue them locally rather than link to a file on a 3rd party website. This avoids loading delays that can occur on your site if the other site is experiencing problems or slow performance.

Next, we cover how to include scripts and other PHP libraries.

Enqueuing JavaScript

Any new script files should be placed in your child theme’s assets\ js  folder, then enqueued using wp_enqueue_script . This works just like stylesheets:

In the above example, we have specifically hooked wp_enqueue_scripts  to ensure WordPress loads it in the best place (usually after the parent theme scripts in the header). We have also given it a dependency on ‘jquery’ to ensure it does not load unless jQuery is available.

You may want to include other script libraries that are more appropriately loaded into the footer. You can hook wp_footer  to achieve that:

To modify a core Layers script, such as the slider, for example, you cannot copy this script to your child and attempt to load your modified version over the core. Instead, reference the script APIs and include the appropriate jQuery snippets for adjusting any arguments the script accepts and add these to your theme.js. APIs are linked from About Layers.

 Including PHP Files

If you are housing a group of code in a separate PHP file from the functions.php, or need to reference a ready-made PHP library stored in your child theme directory structure, you must use require_once($path)  from the functions.php to help WordPress find the file.

When defining the path, you would use get_stylesheet_directory() instead of get_stylesheet_directory_uri() to return the full server path to your child theme directory.

 

 

Actions allow you to inject a custom function or bit of code into a specific place. You can create a custom Action using the main WordPress Action API to add or remove code from any action present in the theme by specifying any existing Hook. Thus the term “hooking.”

Layers also offers an Action API for hooking into our own custom actions. These allow you to customize templates with your own functions or HTML without having to copy the entire template into your child theme.

For example: You may want to add code to the footer of Layers. This can be accomplished by writing new function containing your custom code, then Hooking it to the wp_footer core action, OR you can use the Layers Action API to take advantage of better placement such as the layers_before_footer_copyright  hook, which will output a custom element just above the copyright bar.

Custom Actions differ from custom Filters because custom Actions allow you to add or remove code from existing Actions. Whereas custom Filters allow you to replace specific data (such as a variable or CSS class) found within an existing Action.

We provide a reference of all Layers actions and filters under the Reference section of this Codex.

Filters are a type of Hook allowing you to change or remove an existing function.

For example, you might want to insert another CSS class in an HTML element, or modify how the Layers breadcrumbs look. Using filters reduces the need for copying whole templates or core files from Layers into your plugin or Child Theme and removes the dependency on you to constantly check for differences in parent updates.

See Using Actions, Filters & Hooks for a full overview of hooking and filtering in Layers

These are added using action hooks and core WordPress functions. See How to Add Custom Widget Areas to Layers

Custom page templates are any special layout you wish to add to the template options in the Page editor.  Custom templates might include various static archive layouts,  custom widget areas, or  support for a special post type introduced in a plugin, such as custom WooCommerce shop layouts.

Adding New Page Templates

In this section we will cover adding of custom templates, versus overriding templates that already exist in Layers or a Layers plugin.

  1. First, determine which core template you want to base your layout from. In most cases, the page.php or archive.php is used depending on if the content is singular or a list of posts, but you might choose archive-product.php or single.php to add a custom widget area below the title on specific views, for example.
  2. Copy the content of your chosen template into a new PHP file.
  3. Replace the heading on your copied template with your custom header, or ensure the Template Name:  attribute is added before get_header()
    • Each new page template Must start with a header identifying the page template name. This name appears in the drop-down on the page editor.

From here, the markup should follow the original template in terms of core structure and CSS classes, hooks etc. You may add custom HTML in addition to this structure, or insert custom classes, though it is best to see if it can be done using hooks or filters instead.

Reference: page.php, archive.php

Example of a customization added to the default markup borrowed from archive.php:

 Line 6-10:  Page Title

Rather than add the page-title  partial to this template to display the Page Title banner, we want to set an H1 heading tag and not output any breadcrumbs or excerpt. See Setting Static Page Titles for more examples.

 

Line 11: Custom container class

A custom class of dynamic-portfolio  is added to the main container wrapper that allows us to add a background color and margins without affecting the framework classes. This could also be done by selecting .page-template-your-template-name-php .container  but this method is far cleaner and more semantic.

Line 12: The Grid

Reference Layers Grids

We want to display our portfolio archive in a grid format, so we need to wrap the loop in

Line 13-21: The Loop

Each template must contain a loop if it intends to output the content of a post or a feed of posts. You can skip the loop if your template does other things like output widget areas exclusively.

In our portfolio example,  we need to show a custom post type, requiring the custom query on line 19. We use wp_query and a set of arguments to grab things like the post type and an infinite number (vs pagination).

The custom query variable is used to modify the loop

Line 22: Article Markup

You can place the markup that defines each individual portfolio post in your list directly inside the loop, or you can place it into a partial and call that partial with get_template_part()

In this example, our partial is inside the theme folder under partials/dynamic-portfolio.php

The following demonstrates how you can adapt an overlay grid style from the Framework pattern page to a post list:

Line 1: Wrap single posts in an article tag and include the WordPress core post ID  and post_class()  handlers so they get their auto-generated classes. You can insert your own classes into post_class() as shown here to set acolumn  width of span-4  from the Layers Grid framework, which sets up a 3 column grid (or 4/12).

Line 2: Link the whole thing to the post it represents. Using $portfolio  here on the_permalink() ensures we grab the permalink for this specific post in the query. The rest comes from the framework pattern we copied in to get the overlay grid style thanks to thumbnail  and with-overlay  classes.

Line 3-16: The rest is the overlay grid style from the framework, using WordPress templating functions to pull in the link, title and excerpt.

Refer to the Framework Grids Reference for examples of span and grid classes

Finishing up

The remainder of your template is closing off your queries and HTML. At the very end, you must call the site footer:

Widget Areas

If you wanted to create a page template that included widget areas or sidebars, you may include them using any of the Layers Sidebar functions or you would register a custom sidebar and output it using a core function like dynamic_sidebar() .

Our portfolio example is full-width by default. Here is how the content markup would look with a sidebar:

Reference: archive.php

We insert the left sidebar on line 3, then wrap the loop in a div that sets the layers_center_column_class(). This ensures we get a blog-style layout before the post grid is output so the sidebar can sit in the right place.

See How to Add Custom Widget Areas to Layers for a detailed walkthrough on setting up custom widget areas.

 

 

Overriding Default Templates

Again, hooking should be used wherever possible to modify existing templates in Layers. There are some cases where you just need to change the template itself, which requires an override. Reasons you might do this are needing to add or remove HTML in a location that is not hooked, adding or changing classes or functions where they can’t be changed through filtering, or adding widget areas.

All you need to do to override a template is to copy it to your child theme directory using the same file structure as the parent. For example, main template files found in the layerswp theme root folder go into the root of your child theme, and those found in the partials sub-folder can go into a partials sub-folder of your child theme. You do not need to add or change template titles, only add your custom code or changes.

There are a few things you should NOT modify in an existing Layers template:

  • Do not change heading types. Layers works extensively with SEO experts to determine the most effective heading and element structure, and headings are directly connected with framework typography styles. (ie don’t override templates to change all  H3  to H1  )
  • Do not change HTML elements/break away from the Layers framework structure (ie don’t override templates to change all <sections>  to <div>  etc )
  • Adding HTML elements is OK.
  • Do not remove default classes or function calls inside the element wrappers or you risk breaking the framework functionality or settings. Adding classes or functions is OK.
  • Do not use query_posts() to modify the default query.

Custom Post Types & Taxonomies

As mentioned in the best practices section of this guide, Custom Post Types are considered back-end functionality and should not be introduced through a child theme. Add them to a Layers Extension plugin instead, and package the plugin with your Child Theme, or offer it separately as an add-on.

See Create an Extension: Adding Custom Post Types & Page Templates

 

Custom Meta fields are simply form fields added to the post editor, customizer or widget options that allow user input. The values of these fields may be submitted and retrieved in a few different ways.

If you are working on a single site install and not a theme/extension, you might find it easier to work with a plugin such as Simnple Meta or  Advanced Custom Fields. Developers may also use extended frameworks like CMB2 or Meta Box in your themes or extensions for more control over repeater and advanced fields.

Custom Fields in Widgets

See the following:

Customizer Controls

If you are looking to add custom fields to the WordPress Customizer, go to the Adding Customizer Sections & Controls developer guide.

Custom Fields in the Editor

There is no special way to add meta to the post editor from a Layers child theme or plugin – it is done the traditional WordPress way. However, you may take advantage of the Layers framework for building the form elements themselves, by extending Layers_Form_Elements via the wonderful input() helper function.

There are two methods for housing your custom meta, via using a traditional procedural structure, or via a PHP class. The following tutorial follows a procedural order. From extensisons, you should use the class structure described here to put the actions into your constructor, and the functions into your main plugin file or class.

Create the file

To begin, create a PHP document called meta.php and save it to your child theme or plugin’s includes folder. Here is the starting structure of our file, which contains a comment describing what the file contains.

You will be creating the following functions in that file, then including it in your theme or plugin’s main functions file.

In this example, I’ll demonstrate how you could add a Photo Credit and Source URL field to posts to support a Magazine-style site. If you have created a custom post type, you can apply this to a different post type easily.

Add the Meta Box

Line 3: Setup your function. This should have a unique prefix to add_meta_box to avoid potential conflict with other themes or plugins (i.e. do not use ‘layers_child_’ as your prefix).

Example:

yourtheme_postype_add_meta_box

Line 6: The

$screens
variable allows you to setup an array of post types you want your meta box associated with. The default in Layers is simply ‘post’.  If your plugin is adding a custom post type, you can add that post type’s slug to the array, e.g.
$screens = array('post', 'my_portfolio');

Line 9: Here we  use  add_meta_boxes  to create the panel. The following parameters are set:

Line 10:  The unique ID for this meta box. We will reference this later when building the fields.

Line 11: The display title of the meta box. Please note: if the meta box you are creating is intended for public release (in a theme, plugin, etc.), this string should be internationalized using _()

Line 12: The name of the function that will output the contents of the meta box.

Line 13: The post type where this meta box should be displayed. Since we are using a variable to define these on line 6,  we set this to

$screen

Line 14: Specifies the section of the page where the meta box should be placed (normal, advanced, or side).

'normal'
places it below the editor.

Line 15: Specifies the order within the section where the meta box will be placed (high, core, default, or low).

'high'
places it above the Layers Options meta panel, directly below the editor.

Now we need to hook this function onto add_meta_boxes:

If you check your Add New Post screen, you should see the box, though you will have a blank panel or an error until the callback function is created.

meta-box2

Build Your Form

The callback we setup on line 11 of our
add_meta_box
function is used to output the meta field’s form elements in our meta box.

Line 5: Create the callback function using the name we already defined

Line 8: Use wp_nonce_field to setup a nonce for security purposes.  There are only two required parameters:

  • Action name: This can be anything, and simply adds context to what the nonce is doing. We are outputting a meta option, so we simply reference
    layers_child_meta_box
    . This should be unique to any other names you define.
  • Nonce name: This is the name of the nonce hidden form field to be created. Once the form is submitted, you can access the generated nonce via
    $_POST[$name]
    . To make it simple we just append our action name to nonce e.g
    layers_child_meta_box_nonce

Line 14-15: Here we set two variables to represent our meta field keys using  get_post_meta, $credit_url and $credit_name, which will correspond to our two fields.

Meta-data is handled with key/value pairs. The key is the name of the meta-data element. The value is the information that will appear in the meta-data list on each individual post that the information is associated with.

$post->ID
retrieves the id of the post being created/viewed/queried
'my_photo_credit'
, or the second parameter, is the meta key name. This should be unique and semantic.
true
is used to return the value

Line 16:  Your form elements go last. For most form elements, you can instantiate the Layers_Form_Elements class and use the input() helper function to generate your form fields. For creating special field types such as a WYSIWYG field, we use core WP functions.

Layers Form Elements

Reference: input()

For our purposes we only need two text fields. You can create text, message, icon/image select, image, file, drop-down, checkboxes and radio buttons using input(), and rich text fields using a special core function. “Fancy” fields such as  color pickers, repeatable fields, etc require additional javascripting explained in separate tutorials.

Line 1-2: We start with a condition that checks to ensure Layers is installed (and thus the class we will be extending exists). This is helpful for avoiding class errors if the user happens to have your extension active but Layers is not installed. Set your

$form_elements
value to
new Layers_Form_Elements

Line 4: (optional) Set your field wrapper. Using a paragraph tag with the

layers-form-item
class will render your field full width like the Video URL field. If you do not use a wrapper, the fields will simply sit next to one another:

meta-box4

Line 5: (optional) add a

<label>
for elements that don’t take a
'label'
argument. Labels should be wrapped in __().

Line 6-16: Setup your input() array. Follow this link for detailed information on each parameter.

Note that we reference our meta key names in each input’s

'name'
and
'id'
value.

We then use our output variables to set the

'value'
of the fields.  By using
isset
, we ensure data is only returned when it exists:
( isset( $credit_url ) ? $credit_url : '' )

Finally, the

'class'
parameter allows us to use the existing framework styles for our fields. This is optional – you can replace our class with your own, if preferred (keep in mind admin CSS must be loaded separately from your front-end CSS). Classes for each field type are referenced in the input() link above.

TinyMCE Fields

One exception for Custom Fields vs Widgets/Customizer controls is the rich-text editor field. In widgets, we can use the input type of
rte
. In the admin, we cannot.  Instead, we use the wp_editor function. In this example, we are still inside our
layers_child_meta_box_callback
function:

mce-field

Saving Meta Data

Line 1: create your save function. Ensure this is unique, i.e.

<strong>yourtheme_custom</strong>_save_meta_box_data

The first part of the function checks to make sure we really want to save the meta input. These lines are based on Tom McFarlin’s

user_can_save()
linked in the References section below. Basically, they make sure that the nonce is valid and this isn’t an autosave, and does it in a very efficient way.

Line 5: The first

$_POST[]
value should be set to your nonce name defined earlier, and the second set to your action name.

The second part of the function checks to see if any data has been entered into the the two fields we created. If there is text to save, it uses the update_post_meta() function to save the text to the database. This function has 4 parameters:

$post_id = The unique ID of the post being saved. Use

$post_id
.
$meta_key = The unique meta key specifying where the input should be saved. In our example, our keys are
'my_photo_credit'
and
'my_credit_url'
which we defined earlier.
$meta_value = The input to be saved to the database.

Lines 13-17: In the code above, we set the required

$post_id
and meta key for each
update_post_meta
function. However, notice that we didn’t give it the meta value of the  input directly. Instead we used sanitize_text_field function to prepare the input before placing it in the database. This isn’t a tutorial about validation and sanitization and not all input types require sanitization, but if you’re working with user input, you should never be placing unchecked user input into the database. Refer to the References section below to check if your field needs a specific sanitization function here.

Now you just need to hook your save function into save_post and you’re done!

Test your code by creating a new post and filling our your fields, then click Save Draft. Your input should be retained after the editor refreshes. If you enable the Custom Fields panel under Screen Options, you should also see your field keys and values:

custom-fields-saved

Include The File

Both theme’s and plugins use require_once() to include files, however the way you set the path is different.

From a plugin, add it to your main plugin file:

From a child theme‘s functions.php you use
get_stylesheet_directory()

Displaying Meta Data

Now that we’ve successfully saved our meta data, it can be displayed anywhere using
get_post_meta()
, the same way we did it above to be used internally.  This can be done directly in a template, or inside a function you hook into a Layers action.

  • Line 2-3: Setup some variables to grab the value of our saved photo credit and photo credit link fields. Make sure you define the correct meta key name, and that the third argument is true to ensure the value is returned as a string and not an array.
  • Line 6: Condition check to make sure there is a photo credit before we bother outputting any additional HTML. This helps avoid empty elements
  • Line 7: Here we wrap our data in a .
    meta-info
    span. This framework style will apply the normal post meta style to these elements, and ensure customizer colors that target the
    meta-info
    class also work. This is is only important if your custom meta data will be paired with the existing post meta. You may apply your own containers and styling for elements used in other ways and locations.

References:

 

WordPress Customizer Controls are the form elements that you see inside the WordPress Customizer which provide options such as color pickers, layouts, styling and widget area selectors . These Controls get assigned to accordion-like groups for organization (panels), making it easier for user to find the options they want.

Customizer controls may be added in both Extensions and Child Themes. The following assumes you have already setup your Child Theme or Layers Extension and are at the point where you are adding custom functions.

Defaults

You may add defaults for the pre-existing Layers controls via the layers_customizer_control_defaults hook as described in the Styling section of this guide. This is recommended in Child Themes where you need to reset the default color controls to ensure your CSS is honored. Click the hook link above to view detailed instructions.

Panels, Sections and Controls

To understand where your customizations will appear, and which element you need to add, the following illustrates the terms we use:

customizer

  1. Panel
  2. Section
  3. Control
  4. Option

The first tier, high level, groups are know as Panels, and those inside them are called Sections, and finally those open up to reveal the Controls containing all the options. WordPress allows theme and plugin developers to add sections and panels using the add_section()   function. Controls are then added to these sections by first registering a ‘theme_mod’ type setting using add_setting()  and then assigning the setting to a Control using add_control()   that will decide how the setting is presented to the user.

We make this process easier by providing a set of filters and keys for building custom controls in a more efficient way.

You can choose to add custom panels to house your new sections and controls, or you can add sections to existing panels or controls to existing sections. Adding to our config array will neatly initialize your controls at the same time the Layers controls are initialized.

Filter Structure

Plugin

You first need to create a custom class to hold your controls inside a new file which we call controls.php.This class is setup just like the main plugin class.

Include this file from inside your main plugin class __construct() or init() function with a simple require_once():

Back to your controls class, setup a handful of helper filters for the panels, sections and controls inside your constructor or initializer. For demonstration we will use init() here so you can see the (small) difference between init() and __construct(). These filters can be used as shown here.

 

The corresponding functions are added along with other public functions in your main plugin class, after the init() function, explained in more detail below.

Child Theme

Your custom controls function in a child theme opens almost identically to an extension, but does not need to define public visibility.

The filter and custom function containing your controls can go into the child theme’s functions.php and requires a unique callback

Example:

The following explains each function in detail and how to format it based on whether you are adding new or adding to.

Custom Panels

Reference: layers_customizer_panels

Plugin

Child Theme

  • Line 1: Safety condition ensures a conflict does not occur if a function with the same name is already run. Choosing unique function names helps avoid this too.
  • Line 2: setup your function to modify the $panels index.
  • Line 3: Set the key or name for your panel, ie ‘mytheme-theme-options’. These should be lower-case and use only – or _ to separate words.
  • Line 4: Set the ‘title’ for your section that displays in the Customizer. Strings should always use l10n methods, ie
    __('string', 'textdomain')
  • Line 5: Set the ‘description’ (optional). This is a short bit of text you can use as instruction or clarification.
  • Line 6: Set the ‘priority’ which is a numeric value that determines where the panel sits sin the list. 130 is a safe choice as it ensures your panel loads below and after the core Layers panels.

Custom Sections

Reference: layers_customizer_sections

Plugin

The panel  value corresponds to the $panels  key, set in the above section as demoextension . If you are not creating a custom panel, then this would be a layers panel ID (see the linked reference above)

Child Theme

Each section should define a title  and the panel  it will be added to. This example shows how you would add a custom section called header-social-media   (Social Media Profiles) to our custom panel called demoextension   (Demo Extension)

Adding Sections to Existing Panels

This example shows how you would add our custom section called header-social-media    (Social Media Profiles) to the existing Header ( header ) panel in Layers. The primary difference here is the array_merge  which takes your section and merges it with the existing ones. You must merge on existing panels, whereas you don’t if using a custom panel.

The following panels are created by Layers:

Panel: Site Settings
site-settings
Panel: Header
header
Panel: Blog

Panel: Footer
footer
Panel: WooCommerce
woocommerce
You can also add custom sections to existing non-Layers panels like the default WordPress panels using the WordPress Core API instead of the Layers filters.

Custom Controls

Reference: layers_customizer_controls

Plugin

In our extension tutorial, we create a custom post type and add a few custom fields to it like a Credit Name, URL and Photo description. Our custom controls will add the option to show or hide this meta on single posts using our post type, in addition to basic meta like the date or sidebars.

The important bit here is the array merge, which takes these custom controls and adds them to the overall controls array for loading.

Each control group uses an array to define itself, ie demo-post-options . At a minimum you need a type   and label   within each individual option.

Child Theme

This example shows how you would add some text fields for entering Social Network URLs in the custom section header-social-media referenced in our custom section above:

$controls [‘section-name’] = In our example, our section is called header-social-media . Each option sets up its own array that must have a title and label.

type

Defines the type of control.

See layers_customizer_controls for a list of available types

label

The title. This should use l10n method
__()
to wrap the value

placeholder

Used in combination with a type of layers-text , layers-textarea , layers-rte  or layers-code  element, and sets some default text inside the field to use an example or instructions.

description

Long-form text describing what your control is used for (optional). Descriptions should be formatted with sprintf and use l10n

choices

Used in combination with a select type to define the drop-down options. The below example shows how we add a Widget Areas option using the layers-select type and populate the drop-down with 0-4 using choices.

Adding Controls to Existing Sections

In the above example we set the section name in the $controls array, then return $controls. When adding controls to an existing section, we need to use an array_merge before returning the $controls to set the section.

You can reference the available key names for the Layers Sections  in the $controls  array in core/customizer/config.php

In the following example, we setup a custom controls array $social_media_controls , then merge it with the $controls array in the header-layout section. See how the syntax varies slightly:

The following Panels and Sections already exist in Layers, which can be extended by adding your custom controls to the relevant section where header-layout is used in the above example:

  • Panel: Site Settings
    site-settings
    • Section: Logo & Title
      title_tagline
    • Section: Navigation
      nav
    • Section: Site Colors
      site-colors
    • Section: Sidebars
      content-sidebars
    • Section: Fonts
      fonts
  • Panel: Header
    header
    • Section: Layout
      header-layout
    • Section: Additional Scripts
      header-scripts
  • Panel: Footer
    footer
    • Section: Layout
      footer-layout
    • Section: Customization
      footer-customization
    • Section: Text
      footer-text
    • Section: Additional Scripts
      footer-scripts
  • Panel: WooCommerce
    woocommerce

WordPress offers the following defaults:

  • title_tagline – Site Title & Tagline
  • colors – Colors
  • header_image – Header Image
  • background_image – Background Image
  • nav – Navigation
  • static_front_page – Static Front Page

You can also add custom controls to existing non-Layers sections like the default WordPress sections  using the WordPress Core API instead of the Layers filters.

This should give you an idea of the general format of a control, and for more examples you can have a look in core/customizer/config.php where you’ll see all the controls that we initialize in Layers.

Removing or De-registering Existing Controls

We do not recommend doing this in commercial prodicts. See layers_remove_config_element() for details on how to use this filter when necessary.

Setting Selectors for Color Controls

If you have setup a custom control with a type of layers-color  , you will need to link it to the element it needs to modify, then output the CSS correctly using layers_inline_styles . This ensures the customizer option overrides everything else, absolutely. It also allows you to tap into the invert control that helps text elements adjust automatically depending on if the user chooses a light or dark background color. This can help you set shortcuts and cut down on the number of color controls.

You can see how we do this for the default color controls in core/helpers/template.php inside the layers_apply_customizer_styles() function.

The first value wp_enqueue_scripts allows you to hook your function into the pre-existing lineup of scripts and let’s WordPress manage when the script fires and where in the source it is output. The second value defines your function name and the third is the priority. 100 is a safe number and is more important to plugin authors.

  • Line 1-2 : The above example creates a new function
    layers_child_customizer_styles
  • Line 3: Set up a variable
    $widget_title_color
    that will represent the user’s choice. We use
    layers_get_theme_mod()
    to grab our custom control
    widget-title-color
    defined on line 4 (assuming we created one with this key name using the above Custom Control methods)
  • Line 5:TRUE corresponds to$allow_empty  and should always be true for colors, so don’t worry about that!
  • Line 7:  A condition to ensure the option is set. If it is blank, no inline CSS will be output.
  • Line 8: Finally, we setup our inline css using layers_inline_styles()

This code goes in your theme’s functions.php or inside your plugin’s class where all other custom hooks go, NOT inside your custom controls, sections or panels functions!

Using Option Settings on the Front-End

To utilize a setting in the front end on Layers, we use a helper function called layers_get_theme_mod()  which works just like the WordPress core get_option().

Plugin

Each $option  for layers_get_theme_mod($option)  is the custom option name you setup in your custom controls array. This example shows how we would use a condition to determine whether a sidebar is added to the demo post view depending on the option choice.

 

Child Theme

In the following example we will add some social icons, corresponding to the networks set in these options, to the header of Layers using the layers_after_logo hook. This goes into your functons.php or plugin class where all other hooks are set.

Layers offers a way for you to export any single Layers Template page and then pack it together with Custom CSS and an XML export to create a Style Kit so users can import fully-configured page layouts. If you already have a child theme, it is not necessary to package kits along with the theme. Instead, you may integrate the presets directly into the theme by filtering the layers_preset_layouts hook. This sets up your presets under the Layers Add New Page area, enabling users to select one of your custom layouts and load it in one step, compared to the multiple-step style kit method.

Setup Images

Your preset images must be stored in a special folder inside your child theme structure so they can be automatically pulled in by the preset when it is loaded. This cuts down on the margin of error that loading them manually or via XML would introduce. Review Structuring Your Theme if you skipped it previously.

Images used as backgrounds or full-width slides should be at least 1920px wide. Images used elsewhere should be at least 1000px wide. This ensures the theme can generate the appropriate crops and scaled versions while maintaining optimal performance.  Each preset also needs a screenshot in png or jpg format that is 515px wide and at least 350px tall.

  1. In your child theme folder, ensure an assets folder exists
  2. Create a sub folder inside assets called preset-images
  3. Add all images used in your Preset Layouts to this folder root.

Setup Your Demo

Before going forward with preset integration, you will need to setup your child theme and the Layers Pages exactly how you intend them to look when selected by the user. It is always best to do this on a live server, especially if you need to export content to an XML file, as it is the only sure way your users will be able to import the images and other media used. Be sure to upload the images used on the builder pages from the child theme’s preset-images folder. This is a safety step that makes absolutely sure the image file names and location are correctly set in the export.

Export Page Data

Export the pages using the Export function on the page editor as outlined here. This will produce a .json file for each layout that you will need for the next step.

Setup the Function

You may add your custom preset function to your theme’s functions.php file, but the json string can get very long, so you may find it more manageable to create a helperfile such as presets.php, then include it in your functions.php using require_once():

In your presets.php, start be defining your filter:

In the above example, we use layers_child_presets  as our custom function name, where child might be the name of your theme. Lets take a look at the function

Line 1: Filter $layers_preset_layouts

Selecting the $layers_preset_layouts function and defining our own variable $layers_child_presets will allow us to pass our custom array into the Layers Presets so our screenshot and preset loader are visible under Layers → Add New Page. 

Line 3: Set first preset ID

This is the beginning of our preset array and must set a unique identifier for the preset. Here we use first-preset-id , but yours could be my-child-home-preset , etc.

Line 4: Preset Title

The title argument takes a simple string, which you should internalize it with __()  so it can be translated.  child-theme-slug  is your main theme slug as defined in your localization function, or can be replaced by a theme name constant if you chose to use them.

Line 5: Screenshot URL

For best performance, store your preset screenshot in the preset-images folder. We use get_stylesheet_directory_uri() to determine the URL path to the child theme root.

Line 6: Screenshot Type

Ensure the file extension on the image in your screenshot url is correct and matches this value.

Line 7: Json

This is the fun part! Well not really. But the results are worth the few minutes of intense concentration this step requires. The json argument is looking for the entire contents of your export file, sandwiched between those two tiny single quotes. Extra characters and spaces can break it. A missing bracket can break it. As a Layers Child Theme Developer, you can do this!

  1. Open the export .json file for this preset, preferably in a plain-text editor or program such as Sublime Text.
  2. Ignore any scary syntax error your HTML editor may throw. It is a false positive.
  3. Copy the entire file contents with Cmd+A / Ctrl+A
  4. Return to your function and place your cursor gently between the single quotes of this json line and hit Cmd+V / Ctrl+V
  5. You should now have a gigantic block of code that begins and ends with a fancy bracket, snuggled between the single quotes. This code will be loaded into a new page when your preset is selected by the user, just like the import process, and all images automatically reconciled with the files in your preset-images folder and pulled into the Media Library automatically.

Line 10: Return

Finally, we merge our custom arrays with the original using array_merge()  and return  our results. Remember, you must always have a return in combination with a filter hook.

Test It!

Activate  your child theme on a fresh WordPress setup that does not have the layouts or images yet.

Go to LayersAdd New Page and verify your presets appear.

 

 

Onboarding refers to the process your users go through to get started using your theme or plugin. In Layers and the official extensions, we do this via an activation redirect that sends users to a simple “setup wizard” that takes them through a few brief introductions with videos, and ends up in the Customizer where they can immediately begin using the tools.

In addition to the Oboarding process, you may wish to incorporate a static help page within the WordPress admin so users can easily access written documentation or links to your website and other resources.

In general, we do not allow the removal or modification of the Layers Dashboard from commercial child themes or extensions, but you can easily add your own onboarding and help page to the Layers menu.

If you’re just looking for a way to add your logo in the WordPress admin and hide some menu options for a client site, check out our tips on White-labelling the WordPress Admin.

Admin Menu Links

The method is slightly different in how you inmplement these links from a Layers Extension or Child Theme, but both use add_submenu_page()

From within a plugin class:

Line 3: The menu slug of our Layers menu, which is

layers-dashboard

Line 4: The title of our page, encapsulated in __()

for translation. Our slug constant represents the textdomain value.

Line 5: The name of our menu link as we want it to appear, encapsulated in __()

for translation. Our slug constant represents the textdomain value. The shorter the better.

Line 6: The minimum capability the user must have to access this page. Refer to capabilities in WordPress or use the default edit_theme_options

Line 7: The slug of your page. Make sure this is unique, ie don’t name it “settings” or “get-started”. Slugs are lower-case and must use hypens to separate words.

Line 8: The callback, looking for the instance ($this ) of the load_onboarding function which comes next

Line 12: The load_onboarding  function simply grabs our onboarding page template.

Line 13: We’re using require_once so inside the partial we can use $this  to access the header and footer.

Our  constant LAYERS_DEMO_EXTENSION_DIRis used to path to the plugin directory. You would use your plugin’s constant here.

Now hook it to admin_menu from within your __construct() or __init()  and give it a priority of 60

From within a child theme’s functions.php:

The add_submenu_page()  function takes the following:

Line 4: The menu slug of our Layers menu, which is layers-dashboard

Line 5: The title of our page, encapsulated in __()  for translation. Our slug constant represents the textdomain value.

Line 6: The name of our menu link as we want it to appear, uses __()  for translation

Line 7: The minimum capability the user must have to access this page. Refer to capabilities in WordPress or use the default edit_theme_options

Line 8: The slug of your page. Make sure this is unique, ie don’t name it “settings” or “get-started”. Slugs are lower-case and must use hypens to separate words.

Line 9: The callback function that will hold our page template location

Line 14: Create the callback function using a unique name.

Line 15: Pull in the page template (located in our child theme’s includes folder) using get_stylesheet_directory()

Line 18: Hook your menu function into admin_menu and be sure to set a priority of 60 or higher.

Admin Pages

For both onboarding or free-form admin pages, your template only requires one thing, which is the section  wrapper with the l_admin-area-wrapper   class:

What you put inside the wrapper is up to you. In general though, keep the following things in mind:

  1. Your admin page should not directly compete with the Layers Marketplace page (but you can certainly link/showcase your own products)
  2. Admin pages should not contain any Theme or Plugin Options that affect the front-end – put these in the Customizer using Customizer controls instead!
  3. Plugins with special plugin-specific settings (that are not linked to front-end display such as our DevKit options) should be linked from the Settings menu rather than the Layers menu.

In most cases, Layers Child Themes do not need additional onboarding and will be sent to the core setup wizard found under Layers Get Started, but you can use the get-started template as a way to add your own interactive help pages or introduction.

onboarding

Refer to the demo theme or extension files to see how they are put together and can be customized for your project, or use the browser inspector to see the HTML used on the Layers Setup page to produce the guided tour. Because core setup is implemented differently than you do it from a plugin or child theme, you cannot copy the core files to your project to make onboarding work!

Redirecting on Activation

Plugins

First we use set_transient() in a new function in our plugin class to create a transient we will reference to determine if the redirect needs to happen or not and give it a priority of 30 to ensure it fires after Layers has loaded.

Then we setup the redirect:

Line 3: We use current_user_can()  to set a minimum capability of manage_options for this page to be displayed, as it contains links you may not want authors or subscribers to access.

Line 4: Here we use get_transient() to check for our layers_demo_extension_activated    transient. This ensures the redirect only happens on activation.

Line 6: With wp_redirect we can use admin_url to set the path to our page by the slug we defined earlier in our add_submenu_page  function. Finally, hook it from inside your __contruct() or __init()

Child Themes

Child Themes will redirect to the Layers Getting Started by default. We really recommend keeping it this way for users who have never used Layers before and would benefit from the introduction. However, if you have customized the Layers onboarding, you can redirect to your page instead with
wp_safe_redirect()
inside a custom function in your theme functions.php

Line 2: This checks to see if the user has just activated the theme from the Themes page. If so:

Line 3: Set the layers_welcome  option to 1 (true) – this option is created by the Layers core.

Line 4: wp_safe_redirect to the admin_url using the page slug we defined earlier in our add_submenu_page function.

Line 7: Hook our function into after_setup_theme and give it a priority of 30 to ensure it runs after Layers.

To add a translation to your child theme, first register your child theme text domain in your functions.php.

The easiest way to prepare your translation is to use a plugin like Loco Translate.You may also prepare these translations using a tool like poedit. See Translation tips for general expectations on how to make a good theme translation. Your .po and .mo files should be stored inside a languages folder in your child theme folder.

 To translate Layers text, please consider contributing to the core by sending us a Pull Request, or emailing your translation files to us.

Layers is a unique page/site builder & theme framework for WordPress. Child themes for Layers can provide additional advanced styling, templating, and actions/filters.  The following guidelines are tailored to commercial themers looking to submit official Layers WP Child Theme items to ThemeForest. Even if you plan to sell your theme independently, we recommend using these guidelines as a checklist to ensure the easiest maintenance and best success for your product.

Upload Requirements

  • Layers Child Themes should follow all standard WordPress Theme submission requirements on ThemeForest. The Themeforest theme checker plugin helps a lot in clearing these hurdles, as does the regular Theme Check plugin from wordpress.org. Keep in mind you only need to worry about checking YOUR theme, not Layers.
  • The Layers theme should not be included in the child theme zip file. Include a prominent link to http://www.layersp.com in the Item Description and the documentation. You may copy or include our install guide to help.
  • Child themes must include an index.php file or they will not be able to be uploaded to ThemeForest. If the child theme doesn’t need to customize the parent theme’s index.php, just call the parent’s index.php file from your child theme’s index.php file. For example, the index.php file should look like this:

Item must have the following at the top of your product description on Themeforest to help buyers know that the item is dependent on Layers.

Technical Requirements

  • The child theme should follow a similar file / folder structure as the Layers theme framework itself as in the following example:
      • Child Theme Folder /
        • assets /
          • preset-images/
          • css /
          • images /
          • js /
            • theme.js
        • languages /
        • partials /
        • functions.php
        • style.css

CSS & Styling

  • CSS rules must be specific enough to override the CSS used by the parent (LayersWP) without using !important. For more information on CSS Specificity see this article.
  • Child Theme should not de-queue or re-enqueue the parent stylesheets
  • FontAwesome is already in Layers, do not enqueue or include it twice
  • Google fonts are already  in the Layers framework, you do not need to include the library twice. Set fonts in the Customizer Defaults only.
  • Font icon libraries, if included in your theme, must be placed in a subdirectory of the child theme’s assets folder.
  • Additional font styles and @font-face CSS should be kept in a separate “fonts.css” stylesheet.
    • The “fonts.css” stylesheet must be enqueued as a dependant of the Layers theme framework.css stylesheet to ensure it loads before the child stylesheet.
  • Layers Customizer defaults must be setup in the functions.php to allow basic color, layout and font customization and be verified to work (ie your CSS styles should not oiverride the user’s customizer choices). See layers_customizer_control_defaults for detailed usage.

JavaScript

  • Additional JavaScript files must be placed in the child theme’s “assets / js” subdirectory.
  • Modifications to core Layers scripts (such as the slider) must not attempt to load a modified copy of the script over the core version.  You should use the script’s API or jQuery snippets to modify arguments instead

PHP & Templates

  • Including separate PHP files or libraries must be done using the “require_once()” method from within the child theme’s “functions.php” file.
  • Any page templates added to the child theme must use the Layers framework HTML structure, classes, and functions for calling elements like sidebars (as per the default Layers page template).
  • Child Themes must not modify the following elements in existing Layers templates:
    • Do not change template heading types.  Headings have been optimized for SEO purposes and are directly connected with framework typography styles.
    • Do not swap out HTML elements or break away from the Layers framework structure (e.g. changing all <h3> to <h1>).  Adding HTML elements is okay.
    • Do not remove default classes or function calls inside the element wrappers, as doing so may break framework functionality or settings.  Adding classes or functions is okay.
    • Do not use the “query_posts()” function to modify the default query.
  • When registering new sidebars, you must not use simple numbers or generic ID values such as “sidebar”, “widget-area”, or “widgets”.  Sidebar IDs must be lower-case and use hyphens to separate words.
  • Custom widget areas must use the safety condition “is_active_sidebar” to ensure no naming conflict with other plugins.
  • Child themes must not introduce any content related functionality, such as Custom Post Types, Custom Taxonomies, shortcodes, etc.  These should be handled by a separate extension plugin, and may be packaged with your Child Theme and/or offered separately as an add-on.

Child themes should include additional Preset Layouts, in order to improve the performance of the Layout generator, all images used in your preset layouts can be added to the assets/preset-images/ folder.

Plugin Requirements

You should not require 3rd party plugins in your themes, but can include a notice that requires installation of your own plugins that are bundled with the theme (such as a widget extension) or suggest compatible plugins in your documentation (such as recommending Contact Form 7). This includes ensuring your theme is not dependent on any commercial plugin the user would have to buy for your theme to work. the only exception here is Layers Pro, which can be bundled with a Developer License. You are then responsible for getting updated versions to your users as soon as possible after we release them.

Do not include 3rd party plugin frameworks such as CMB etc that require the user to install developer plugins. These can introduce bugs and other compatibility issues that you will then have to depend on someone else to fix, which only increases your support load. See our developer documentation for how to add custom fields and page templates etc without depending on these libraries.

You may not bundle other Layers extensions in your theme that you did not create unless you have a developer or reseller license that allows you to do so, nor can you simply rename those plugins or copy the widgets from them into your theme or extension. Include copies of dev licenses in your theme package or readme where needed. For information specific to Layers Pro, see this article.

Selling Themes

Our official marketplace is Envato. The above requirements, and any Envato-specific requirements are found on the Envato Author Child Theme submission guidelines

Envato is exclusive in that they have partnered with us to ensure Layers products sold through them are tested and compatible with Layers, and receive the best marketing and visibility via their Layers product category. Themeforest is the only marketplace where official Layers products (made by Obox) are sold.

You are not required to sell your themes on ThemeForest and are free to offer your themes on your own marketplace or a competitor such as Creative Market. The downside of using independent marketplaces is that they do not receive the same marketing, visibility through the Marketplace tab in Layers, or developer support. We welcome you to get in touch with us if you have questions about sales outlets, or just want to make us aware of a product you have that is doing well on a different Marketplace (we love success stories!)

Documentation Requirements

Themes submitted to Themeforest need written documentation to help buyers with installation, setup, and customization.

We recommend you include a link to your documentation when submitting the theme, and also a link to these guidelines to remind the reviewer that they must only review YOUR child theme, NOT Layers. It may also help to include a copy of a clean W3 Validation of your theme’s HTML if it has any and remind the reviewer that all HTML output on your demo is being handled by Layers, not your child theme othewise.

Support Requirements

You are responsible for supporting issues specific to your child theme including install, customization, updating and troubleshooting.  Issues we receive through Layers Messenger that turn out to be theme related will be referred to you.

Themes that are not updated to support major changes to Layers may risk removal from ThemeForest, so please subscribe to our newsletter to ensure you receive important notifications about beta releases and pending changes. We may advise your users to deactivate or refund themes that are found to be broken, incompatible or causing conflicts if they are not updated within 14 days of major releases.

Additional Resources

Last Updated: